6

私は、同じであるが異なるアリティを持つ2つのメソッドを持つJavaクラスを持っています(1つは引数をとらず、もう1つは1つの引数を取ります)。この両方のメソッドをオーバーライドするプロキシを作成します。問題は、このjavaクラスからno-argメソッドが呼び出された場合、プロキシの代わりに基本実装が呼び出されることです。しかし、objで直接no-argメソッドを呼び出すと、正しいプロキシメソッドが呼び出されます。誰かがこの振る舞いを説明できますか?

Test.java:

package example;

public abstract class Test {

    public void callMethods(Object obj){
        callMethods();
        callMethods2();
    }

    public void callMethods() {
        System.out.println("Default callMethods");
    }

    public void callMethods2() {
        System.out.println("Default callMethods2");
    }

}

run.clj:

(let [obj (proxy [example.Test] []
            (callMethods
              ([] (println "Overridden callMethods"))
              ([obj] (proxy-super callMethods obj)))
            (callMethods2
              ([] (println "Overridden callMethods2"))))]
  (.callMethods obj)
  (.callMethods obj :test))

出力:

Overridden callMethods
Default callMethods
Overridden callMethods2

期待される出力:

Overridden callMethods
Overridden callMethods
Overridden callMethods2
4

1 に答える 1

5

プロキシは、このオブジェクトに対してプロキシしているメソッドのマップを維持します。このマップ内のすべての呼び出しはそのメソッドで処理され、他の呼び出しはオブジェクトを呼び出します。proxy-super関数メソッドマップからそれ自体を削除し、それ自体を呼び出し、それ自体を後書きに戻すことによって、それは魔法ですか?呼び出し中、プロキシオブジェクトのそのメソッドへの呼び出しはすべて、プロキシされたオブジェクトにフォールスルーされます。

  • 出力の最初の行はプロキシされた呼び出しからのものであり、オーバーライドされた出力が表示されます
  • 2行目は、引数がゼロのsuperのメソッドからのものです。これは、その呼び出しが発生したときに、オーバーライドするメソッドがオブジェクトのプロキシメソッドマップにないためです。
  • 3行目は、そのメソッドがオブジェクトのプロキシされたメソッドマップにあるため、プロキシされます。

非常によく似たシナリオが、この投稿の最後にMeikelBrandmeyerによって説明されています。答えはプロキシの代わりにgen-classを使用することだと思います

于 2012-10-30T09:39:14.747 に答える