0
public class Print1 {
    int x = 1;
    public void print(A a) { System.out.println(x); }
    public void print(B b) { System.out.println(x+1); }
}      

public class Print2 extends Print1 {
    int x = 3;
    public void print(A a) { System.out.println(x); }
    public void print(B b) { System.out.println(x+1); }
    public void print(C c) { System.out.println(x+2); }
}

// a tester class with main method 
A a = new A(); B b = new B(); C c = new C();
Print1 p1 = new Print1();
Print2 p2 = new Print2();
p1 = p2;

 System.out.println(p1.x); // Call 1, p1 is from Type Print1
 p1.print(c); /* Call 2
 //p1 is from Type Print2, print(B b) will be called */`

クラス B はクラス A のサブクラスであり、C は B のサブクラスです。

  1. タイプのオブジェクトを参照しているのにP1タイプからのコール1で、コール2でオブジェクトへの参照として動作しているのはなぜですか?Print1Print2Print2

  2. なぜ Call 2print(B b)は fromPrint2ではなく from で呼び出されるのprint(C c)ですか?

これは、これまでJavaで最も混乱していたことです。ご協力ありがとうございました。

4

2 に答える 2

0

変数の型は、アクセスされるクラス メンバーを決定するために使用されます。

したがって、 は のフィールドではなく、のフィールドp1.xを参照します。(から削除すると、コンパイル時にエラーが発生します。) のフィールドは別のフィールドです。つまり、オブジェクトには 2 つの異なるフィールドがあります。xPrint1Print2xPrint1xPrint2Print2int

また、メソッドがないため、メソッドが式print(B b)で使用されます。(またはを拡張しない場合、コンパイル時エラーになります。)の実装をオーバーライドするため、その実装が使用されます。p1.print(c)Print1print(C c)CBAPrint2Print1.print(B b)

于 2015-08-05T14:35:39.123 に答える
0

最初の印刷は、可変シャドウイングにより期待どおりに機能します。

typeのヒープ上のオブジェクトを指す変数p1(type ) があります。thisからの継承が許可されているため。また、変数にはポリモーフィズムがないため、の変数にアクセスできます。変数は互いに「オーバーライド」できません。変数の型によって、何をフェッチするかが決まります。Print1Print2Print2Print1xPrint1x

クラスに別の変数int yを追加すると、混乱が少なくなります。問題なくPrint1アクセスできたはずです。System.out.println(p1.y);


2 番目のものも、ポリモーフィズム(継承による) により期待どおりに機能します。

method はオブジェクトに対して実行されるためprint(c)、オブジェクトは明らかに型Print2です (変数の型 (Print1またはPrint2) は関係ありません。 のメソッドを使用しますPrint2。単にPrint2のメソッドが のメソッドをオーバーライドしたためPrint1です。

于 2015-08-05T14:14:54.163 に答える