Méthode de visite générique

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.

Le visiteur d'expression

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);
} 

L'évaluateur

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);
  }
} 

Les tests

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));
  }
}
© 2006

\Nouveau et intéressant