Я имел дело с hibernate, пытаясь выяснить класс времени выполнения за прокси-серверами, используя шаблон посетителя. Затем я придумал подход AbstractVisitable
, но мне интересно, будет ли он всегда давать правильные результаты.Java абстрактный посетитель - гарантированный успех? Если да, то почему?
Рассмотрим следующий код:
interface Visitable {
public void accept(Visitor v);
}
interface Visitor {
public void visit(Visitable visitorHost);
}
abstract class AbstractVisitable implements Visitable {
@Override
public void accept(Visitor v) {
v.visit(this);
}
}
class ConcreteVisitable extends AbstractVisitable {
public static void main(String[] args) {
final Visitable visitable = new ConcreteVisitable();
final Visitable proxyVisitable = (Visitable) Proxy.newProxyInstance(
Thread.currentThread().getContextClassLoader(),
new Class<?>[] { Visitable.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
return method.invoke(visitable, args);
}
});
proxyVisitable.accept(new Visitor() {
@Override
public void visit(Visitable visitorHost) {
System.out.println(visitorHost.getClass());
}
});
}
}
Это делает ConcreteVisitable
, который наследует accept
метод от AbstractVisitable
. В C++ я бы счел это рискованным, поскольку в AbstractVisitable может ссылаться на AbstractVisitable::this
, а не ConcreteVisitable::this
. Я был обеспокоен тем, что код при определенных обстоятельствах будет печатать class AbstractVisible
. Однако код выше выводит class ConcreteVisitable
, хотя я скрыл реальный тип за динамическим прокси (самый сложный случай, который я мог бы придумать). Является ли подход абстрактного посетителя выше гарантированного, чтобы работать, или есть некоторые подводные камни с этим подходом?
Какие гарантии даны в Java относительно указателя this
?
Приятный завершающий «getClass() является виртуальным» был ключевым фактом, который я наблюдал. –