0

訪問者パターンを使用して、プロキシされたインスタンスの背後にあるランタイム クラスを把握しようとして、休止状態を扱っていました。そこで、あるアプローチを思いついたの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を継承するが作成されます。C++ では、 AbstractVisitableでは ではなくを参照する可能性があるため、これは危険であると考えます。特定の状況下でコードが出力されるのではないかと心配していました。しかし、上記のコードは を出力しますが、実際の型を動的プロキシの背後に隠しています (これは私が思いつくことができる最も困難なケースです)。上記の抽象的なビジター アプローチは動作することが保証されていますか、それともこのアプローチにはいくつかの落とし穴がありますか?acceptAbstractVisitablethisAbstractVisitable::thisConcreteVisitable::thisclass AbstractVisibleclass ConcreteVisitable

thisポインタに関してJavaでどのような保証が与えられていますか?

4

2 に答える 2

2

thisご想像のとおり、常にこのオブジェクトを指しています。非仮想のもの (プライベート フィールド/メソッド、または神が禁じている静的メソッドなど) を参照するために使用している場合を除き、階層内のどのタイプから使用するかは関係ありません。 getClass()仮想です。

thisJava に複数のディスパッチがあると考えて、 の動作を混乱させているのではないかと思います。そうではありません。ビジターを次のように変更した場合:

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

Javaは二重ディスパッチを実行しないため、実際には「ConcreteVisitable」ではなく「Visitable」と出力されます。

于 2010-06-14T14:10:27.963 に答える
0

動的プロキシは、accept(...) 呼び出しを基礎となる Visitable に渡します。次に、visit(...) を呼び出し、それ自体を引数として渡します。プロキシは、accept() 呼び出しを通過する以外には決して関与しないため、visit(...) メソッドの実装に到達するまでに、処理される Visitable は具体的なインスタンスであり、プロキシが取り除かれます。

于 2010-06-14T15:04:35.403 に答える