Java абстрактный посетитель - гарантированно добиться успеха?Если так, то почему? - PullRequest
0 голосов
/ 14 июня 2010

Я имел дело с hibernate, пытаясь выяснить класс времени выполнения за прокси-экземплярами, используя шаблон посетителя. Затем я придумал подход AbstractVisitable, но мне интересно, будет ли он всегда давать правильные результаты.

Рассмотрим следующий код:

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 ++ я бы счел это рискованным, поскольку this в AbstractVisitable может ссылаться на AbstractVisitable::this, а не ConcreteVisitable::this. Я волновался, что код при определенных обстоятельствах напечатает class AbstractVisible. Тем не менее приведенный выше код выводит class ConcreteVisitable, хотя я скрывал реальный тип за динамическим прокси (самый сложный случай, который я мог придумать). Гарантируется ли работоспособность подхода абстрактного посетителя выше или есть некоторые подводные камни в этом подходе?

Какие гарантии даются в Java в отношении указателя this?

Ответы [ 2 ]

2 голосов
/ 14 июня 2010

this всегда указывает на этот объект, как вы можете догадаться. Какой тип иерархии вы используете, он не имеет значения, если только вы не используете его для ссылки на не виртуальные вещи (например, частные поля / методы или, не дай Бог, статические методы). getClass() является виртуальным.

Теперь я ожидаю, что, возможно, вы путаете поведение this, полагая, что Java имеет многократную диспетчеризацию. Это не так. Если вы измените своего посетителя на это:

class Visitor {
    public void visit(Visitable visitorHost);
    public void visit(ConcreteVisitable visitorHost);
}

А потом реализовал это так:

public void visit(Visitable visitorHost) { 
   System.out.println("Visitable"); 
}
public void visit(ConcreteVisitable visitorHost) {
   System.out.println("ConcreteVisitable"); 
}

Это действительно выдает «Visitable», а не «ConcreteVisitable», поскольку Java не выполняет двойную отправку .

0 голосов
/ 14 июня 2010

Ваш динамический прокси передает вызов accept (...) базовому Visitable, который затем вызывает visit (...), передавая себя в качестве аргумента. Прокси-сервер никогда не участвует ни в чем, кроме прохождения вызова accept (), поэтому к моменту, когда он приступает к реализации метода посещения (...), рассматриваемый объект Visitable является конкретным экземпляром, лишенным прокси.

...