On peut améliorer la lisibilité du code du visiteur d'expression arithmétique en utilisant les types génériques. Il est tout d'abord nécessaire de redéfinir l'interface Expression
package oqube.visitor.java5; public interface Expression { <T> T visit(ExpressionVisitor<T> v); }
On notera l'utilisation d'un type-paramètre pour la méthode de visite. Comme pour le cas sans génériques, on a comme implantation standard:
previous public <T> T visit(ExpressionVisitor<T> v){ return v.visit(this); }
Les classes d'expressions sont par ailleurs identiques aux classe précédement définies et ne sont pas redétaillées ici.
L'interface ExpressionVisitor correspondant à ces différentes implantations d'Expression devient naturellement:
package oqube.visitor.java5; public interface ExpressionVisitor<T> { T visit(Add add); T visit(Mult mult); T visit(Neg neg); T visit(Literal lit); T visit(Var var); }
Le code de l'évaluateur est ainsi considérablement allégé, même s'il n'est probablement pas plus efficace:
package oqube.visitor.java5; import java.util.Map; public class Eval implements ExpressionVisitor<Integer> { // a map from String to Integer objects private Map<String,Integer> env; public void setEnv(Map env) { this.env = env; } public Integer visit(Add add) { return add.getLeft().visit(this) + add.getRight().visit(this); } public Integer visit(Mult mult) { return mult.getLeft().visit(this) * mult.getRight().visit(this); } public Integer visit(Neg neg) { return -neg.getSub().visit(this); } public Integer visit(Literal lit){ return lit.value; } public Integer visit(Var var) { return env.get(var.var); } }
Pour tester notre évaluateur, on peut écrire le code suivant (utilisant la version 3.8.1 de JUnit):
package oqube.visitor.java5; import junit.framework.TestCase; import java.util.Map; import java.util.HashMap; public class EvalTest extends TestCase { public void test01Eval() { Map<String,Integer> env = new HashMap<String,Integer>(); env.put("x",12); Eval ev = new Eval(); ev.setEnv(env); // construct an expression Add add = new Add(); add.setLeft(new Literal(10)); add.setRight(new Var("x")); assertEquals((int)22,(int)add.visit(ev)); } }