2

次のコードを実行すると、明らかに「B1/A2/B2」が出力されます。現在、代わりに「A1/A2/B2」を出力することは可能ですか (つまり、A#method2() は B ではなく A で method1() を呼び出す必要があります)。

注: ポリモーフィズムをパスする必要はありません。この質問は単なる好奇心からのものです。

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

    public void method2() {
        method1();
        System.out.println("A2");
    }
}

class B extends A {
    @Override public void method2() {
        super.method2();
        System.out.println("B2");

    }

    @Override public void method1() {
        System.out.println("B1");
    }
}

public class Tmp {
    public static void main(String args[]) {
        B b = new B();
        b.method2();
    }
}
4

6 に答える 6

5

私はそうは思いません。method1()サブクラスでオーバーライドしている場合ではありません。本当にその動作が必要な場合は、A.method1()as として宣言するfinal必要があり、 では定義できませんでしたB

これを行うのは私には意味がありません - 必要だと思うなら、あなたのデザインを再考するべきです!

于 2009-04-24T04:47:17.657 に答える
1

はい、できます。パッケージaでAを定義します:

package a;
public class A {
    void method1() {
        System.out.println("A1");
    }
    public void method2() {
        method1();
        System.out.println("A2");
    }
}

パッケージbでBを定義します:

package b;
import a.A;
public class B extends A {
    @Override public void method2() {
        super.method2();
        System.out.println("B2");
    }
    void method1() {
        System.out.println("B1");
    }
}

テストをパッケージaに入れて、実行します。結果はA1/A2/B2です。もちろん、これは不健康です。method1で@Overrideを省略する必要があることに注意してください。これを元に戻すと、コンパイラエラーが発生します。

method does not override or implement a method from a supertype
于 2009-04-24T06:04:48.110 に答える
1

これを行うには、method1non-virtualをメソッド化する必要があります。それを行うには、それを最終的にします。

  public final void method1() {....

または、プライベートにします。Javaでは、pivateメソッドは常に非仮想です。

   private void method1() {....

(C ++では、プライベートメソッドは仮想または非仮想である可能性があることに注意してください。特に、C ++でのテンプレートメソッドパターンの実装をよりクリーンにします。)

何が起こっているのか:オブジェクト参照(Javaで非静的オブジェクトメソッドを呼び出す唯一の方法)を介して非静的メソッドが呼び出されると、呼び出されるメソッドは、参照されるオブジェクトの実際のタイプ(ポイントされる)によって異なります。 -to)、参照のタイプではありません。

オブジェクトメソッド内では、そのオブジェクトの他のメソッド(またはメンバー)への呼び出しには、暗黙的に「this。」というプレフィックスが付きます。したがって、method2でのmethod1の呼び出しは実際には次のようになります。

public void method2() {
    this.method1();
    System.out.println("A2");
}

そしてthis、オブジェクト参照です。クラスAにあるmethod2では、参照は、this宣言されているかのようにタイプAです。

A this;

しかし、その参照はタイプのオブジェクトを指していますB。Bは派生、継承、サブクラス、is-a 、.であるため、これを行うことができますA

前述したように、「非静的メソッドがオブジェクト参照を介して呼び出される場合、呼び出されるメソッドは、参照のタイプではなく、参照されるオブジェクトの実際のタイプに依存します。」タイプBのオブジェクトをインスタンス化し、me​​thod2()を呼び出すと、this渡された(this実際には非静的関数の非表示パラメーターです)はthis、Bオブジェクトを指すものです。B.method2()がsuper()を呼び出すと、同じことthisがA.method2()に渡されました。

したがって、A.method2()がmethod1()を呼び出したとき、実際に起こったことはthis.method1()、同じthisで呼び出したものです。これは、BインスタンスB化しmain()てmethod2()を呼び出したを参照します。

method1()仮想であり、タイプのオブジェクトへの参照でmethod1()を呼び出しているためB、コンパイラはB、method1()の再定義が呼び出されたものであることを確認します。

于 2009-04-24T06:10:45.880 に答える
0

標準の「自然な」広く受け入れられているJavaメカニズムを使用することはできません。Javaは、finalまたはstatic(またはsuperに呼び出される)でない限り、すべてのメソッドが動的にディスパッチされるように設計されています。メソッドはBでオーバーライドされるため、これらはいずれもオプションではありません。特定の場合に動的ディスパッチを「無効にする」メカニズムはありませんが、必要になることはめったにありません。

リフレクションでこれらの制限のいくつかを克服することができますが、それはスレッジハンマーで貴重な贈り物を開梱するようなものです。

于 2009-04-24T14:25:28.423 に答える
0

私もこの解決策を探していました。それは不可能のようです。基本クラスの変更はオプションではありません。つまり、基本クラスが既に作成されており、そこからクラスを派生させていると仮定すると、基本クラスが独自のメソッドを呼び出し、オーバーライドされたメソッドではないように、派生クラスでできることは何もありません。派生クラスのオブジェクトを作成している場合、基本クラスは独自のメソッドを呼び出す代わりに、派生クラスのオーバーライドされたメソッドを呼び出します。それはおっと....

于 2011-09-22T19:19:37.100 に答える