/** Abstract class for all expressions */ abstract class Expr { abstract T accept(Visitor v); } class Number extends Expr { protected int n; public Number(int n) { this.n = n; } public T accept(Visitor v) { return v.visitNumber(this.n); } } class Sum extends Expr { protected Expr left, right; public Sum(Expr left, Expr right) { this.left = left; this.right = right; } public T accept(Visitor v) { return v.visitSum(left.accept(v), right.accept(v)); } } /** Abstract class for all visitors */ abstract class Visitor { abstract T visitNumber(int n); abstract T visitSum(T left, T right); } /** Example visitor to convert an Expr to a String */ class ToString extends Visitor { public String visitNumber(int n) { return "" + n; } public String visitSum(String left, String right) { return "(" + left + " + " + right + ")"; } } public class ExprVisitor { public static void main(String args[]) { Expr e = new Sum(new Number(3), new Number(2)); ToString printer = new ToString(); String stringRep = e.accept(printer); System.out.println(stringRep); } }