Vamos começar pelas classes que serão visitadas.
class Circle {
public String toString() {
return "Circle";
}
}
class Square {
public String toString() {
return "Square";
}
}
class FunnySquare extends Square {
public String toString() {
return "FunnySquare";
}
}
class ReallyFunnySquare extends FunnySquare {
public String toString() {
return "ReallyFunnySquare";
}
}
Duas são subclasses de Square e para elas não vou criar métodos visit(). O Visitor com reflexão está no código abaixo.
class Visitor {
private void visit(Circle c) {
System.out.printf( "I visited a Circle (%s)\n", c);
}
private void visit(Square s) {
System.out.printf("I visited a Square (%s)\n", s);
}
public void visit(Object e) throws Exception {
visit(e, e.getClass());
}
private void visit(Object e, Class c) throws Exception {
try {
Method m = getClass().getDeclaredMethod("visit", c);
m.invoke(this, e);
} catch(NoSuchMethodException nsme) {
visit(e, c.getSuperclass());
} catch(Exception ex) {
throw ex;
}
}
}
O único método público é o visit(Object e). Ele usa uma versão privada que procura um método adequado para a classe do alvo e, se não achar, recursivamente procura métodos usando a superclasse do alvo.
O código abaixo executa um pequeno teste.
Circle c = new Circle();
Square s = new Square();
FunnySquare f = new FunnySquare();
ReallyFunnySquare r = new ReallyFunnySquare();
Visitor v=new Visitor();
for(Object o : new Object[] {
new Circle(), new Square(), new FunnySquare(), new ReallyFunnySquare()
}) {
v.visit(o);
}
E o resultado é:
I visited a Circle (Circle)
I visited a Square (Square)
I visited a Square (FunnySquare)
I visited a Square (ReallyFunnySquare)
Eu deixei apenas um método visit() público para evitar que o cliente use um método mais abrangente. Como o compilador escolhe o método conforme o tipo da referência e não o tipo do objeto, se for utilizada uma referência com tipo de uma superclasse da instância, perde-se a oportunidade de usar um método mais específico.
Um bônus nisso tudo é que não é preciso usar ifs.
Nenhum comentário:
Postar um comentário