1

このような状況では:

class A{
   public int x = 4;
   public void s3(){
      x = 3;
   }
   public void f(){
      x = 8;
      s3();
   }
}

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

A a = new B();
B b = (B) a;
a.f();
System.out.println(b.x);
System.out.println(a.x);

a.f()f()はクラスの を呼び出しB、次にf()は代入後にs3()関数を呼び出します。この時点で、s3()は でのみ定義されA、値 3 を に代入するとxxはクラス が所有する変数のコピーになりますA。で宣言された をs3()使用しないのはなぜですか? 理論的には、から継承された関数の独自のコピーを持つべきではありませんか? (したがって、継承された in は、宣言されたinを使用する必要があります)xBBs3()As3()ABxB

4

3 に答える 3

0

s3() が B で宣言された x を使用しないのはなぜですか?

通常、親クラスのメソッドは、子クラスのメンバー変数を認識できません。

私はこれをやっていると思います:

B b = new B();
b.f();

あなたの混乱の少なくとも一部を再現するには十分です。B では f() は次のようになります。

class B extends A{
   public int x = 5;
   public void f(){
      x = 10;
      s3();
   }
}

f() は次と同等です。

   public void f(){
      this.x = 10;
      this.s3();
   }

したがって、bf() の呼び出しは、f() が次と同等であることを意味します。

   public void f(){
      b.x = 10;
      b.s3();
   }

次に、A の s3() メソッド内で何が起こるでしょうか。s3() は次のようになります。

public void s3(){
      x = 3;
   }

これは次と同等です。

public void s3(){
      this.x = 3;
   }

「this」はメソッドを呼び出したオブジェクトで、f() の最後の例からわかるように、b です。したがって、s3() は次と同等です。

public void s3(){
      b.x = 3;
   }

つまり、bx は 3 で上書きされます...うーん、それほど速くはありません!

B のインスタンスも A から x を継承します。B の内部では、B の xが A からの x をシャドウすることがあります。その結果、B の f() メソッドは B からの x に代入します。ただし、b が A から取得した x はもうシャドウイングされておらず、A に関する限り、x は 1 つだけです。つまり、A からの x です。にステートメントが表示されます。

s3() が実行された後の最終結果は、b には 2 つの異なる値を持つ 2 つの x があります。B のメソッド内では、B からの x が表示され、A のメソッド内では、A からの x が表示されます。B のメソッド内では、super を使用して A から x を取得できます。

理論的には、B は A から継承された s3() 関数の独自のコピーを持つべきではありませんか?

コピーの観点から考えないでください。クラスからクラスへのポインター、およびクラスからルックアップ テーブルへのポインターの観点から考えてください。通常、コンピュータ プログラミングでは、各インスタンスに独自のインスタンス変数がありますが、メソッドはクラス内のすべてのインスタンスで共有されます。

于 2013-05-21T23:34:35.703 に答える