8
<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test(); // Outputs "B"
?>

Javaで同等のものを取得したいので、次のようなものです

class A {
    public static void who(){
        System.out.println("A");
    };

    public static void test(){
        who(); //<<< How to implement a static:: thing here???
    }
}

class B extends A {
     public static void who(){
        System.out.println("B");
     };

     public static void main(String[] args){
        B.test(); // Outputs "A" but I want "B"
     }
}

PHP 5.3 のようにwho()内部の呼び出しを解決するには、 を呼び出します。A::testB::who

編集:ほとんどの一般的な言語でこれを行う「標準的な方法」がないことは知っています。ハックなどを探しています。また、これは C/C++ やその他の一般的な OOP 言語で可能ですか?

これは、実際の設計のためのものではありません。私はちょうど興味があります。

4

5 に答える 5

2

という名前のメソッドを宣言していなくても、コンパイラB.testはバイトコードでへの呼び出しを生成しているようです。Btest

Bytecode of main method:

invokestatic #5 = Method B.test(()V)
return

クラスとメソッド ("B"および"who") の名前があれば、リフレクションを使用して簡単にメソッドを呼び出すことができます。したがって、質問は次のようになります

B内部のコールスタックとバイトコードを組み合わせて抽出できますA.testか?

スタックに格納された戻りアドレスを使用してB.test、バイトコード内の呼び出しを見つけ、宣言された呼び出しを抽出する必要があります。バイトコード操作ライブラリはたくさんありますが、JVM の実行スタックに関連付けることができるライブラリがあるかどうかはわかりません。

于 2012-07-17T22:45:57.477 に答える
2

Javaではできません。(少なくとも醜いリフレクション ハックがないわけではありません。)

デザインを再考し、適切なオブジェクトに頼ることをお勧めします。

関連する質問:

編集: B.test()への呼び出しにコンパイルされる(または少なくとも仕様によれば可能)ため、 内から呼び出しがどのように行われたかを発見A.test()する方法はありません。つまり、またはを介し​​て呼び出された場合にの動作を依存させる方法はありません。A.test()A.testA.test()B.test()

あなたは好奇心から尋ねているので、これが最も近い「解決策」です。

  1. 目的のメソッドを定義するクラスを引数として取るtestaでオーバーロードします。test(Class<?> c)who
  2. test()クラスで隠します(オーバーライドできないことに注意してください)B
  3. 実装をA.test少し変更します。

コード内:

class A {
    public static void who() {
        System.out.println("A");
    }

    public static void test() {
        test(A.class);
    }

    public static void test(Class<?> c) {
        //who(); //<<< How to implement a static:: thing here???
        try {
            c.getMethod("who").invoke(null); // Call static who on given class.
        } catch (Exception e) {
        }
    }

}

public class B extends A {
     public static void who(){
        System.out.println("B");
     }

     public static void test() {
         test(B.class);
     }

     public static void main(String[] args){
        A.test(); // Outputs "A"
        B.test(); // Outputs "B"
     }
}
于 2012-07-16T21:23:52.677 に答える
1

Java の例を次に示します。Java 8 のデフォルト メソッドとgetClass(). クラスでも機能するに違いありません:

interface A {
    default String name() {
       return getClass().getName();
    }
}

class B implements A {}


public class LateBinding {
    public static void main(String[] args) {

        // Create an anonymous class in `LateBinding` (called `$1`)
        System.out.println(new A(){}.name());

        // Instantiate a new `B`
        B b = new B();
        System.out.println(b.name());
    }
}

結果:

$ javac LateBinding.java && java LateBinding
LateBinding$1
B

ご覧のとおり、メソッドは で定義されていますが、実行中の両方のケースを認識していAます。この例は、静的に呼び出すことができないため、実際には静的ではありませんgetClass()が、PHP の LSB は実際には静的コンテキストに限定されていません。

于 2015-07-28T17:59:49.483 に答える
1

Java で静的メソッドをオーバーライドすることはできません。

http://geekexplains.blogspot.co.uk/2008/06/can-you-override-static-methods-in-java.html

于 2012-07-16T21:26:22.240 に答える
0

静的メソッド宣言でそれを行うエレガントな方法はありません(私が知っているDelphiのみが静的メソッドのオーバーライドをサポートしています)。ただし、静的が必要ない場合は、次のように記述できます。

class A {
    public void who(){
        System.out.println("A");
    };

    public void test(){
        who(); //<<< How to implement a static:: thing here???
    }
}

class B extends A {
    @Override
    public void who(){
        System.out.println("B");
    };
    public void main(String[] args){
        A instance = new A();
        instance.test(); // prints 'A'

        instance = new B();
        instance.test(); // prints 'B'
    }
} 

明確化後の編集:これを行うかなりハックな方法: Thread.currentThread().getStackTrace()次に、最上位のレコード get メソッドと、このメソッドが属するクラスから。クラス c を持つ - c.getMethod("who").invoke(null); と書くことができます。対応する who() メソッドを呼び出します。

于 2012-07-16T21:28:30.257 に答える