x2
コンパイル時の型は ですX
が、実行時の型はY
です。これが意味することは、コンパイラがx2
それについて推論する必要があるとき、それx2
がX
. しかし、実行時には、 の動作は の動作にx2
なりますY
。
では、これをもう少し冗長に説明しましょう。これは合法ではありません:
x2.do2();
これは、コンパイラがそれをx2
であるX
と見なしX
、 という名前のメソッドを持たずdo2
、 しかY
持たないためです。コンパイラは が であることを認識せず、 のコンパイル時の型が であるx2
ことY
のみを認識します。x2
X
ただし、これは正当であり、実行時例外は発生しません。
((Y)x2).do2();
私たちはコンパイラに、ほら、私はあなたよりも について知っていると言っていますx2
。であることはわかっているので、 を受信側としてY
呼び出す命令を発行するだけY.do2
です。x2
さらに、 s を受け入れるメソッドがあると仮定しましょうY
:
void M(Y y) { }
次に、これは合法ではありません。
M(x2);
繰り返しますが、これは、すべての s がs でx2
あるとは限らず、コンパイラーがそれを と見なすためです。そのため、メソッドの呼び出しを拒否する必要があります。X
X
Y
ただし、これは正当であり、実行時例外は発生しません。
M((Y)x2);
繰り返しますが、私たちはコンパイラに、あなたが知っているよりも多くのことを知っていると伝えていますx2
。私はそれが であることを知っているY
ので、私を信じて、あたかもx2
であるかのようにそのメソッドを呼び出してくださいY
。
X
さらに、 で定義され、 でオーバーライドされたメソッドがあると仮定しましょうY
:
class X {
void do1() {}
void N() { System.out.println("X");
}
class Y extends X { void do2() {}
@Override
void N() { System.out.println("Y");
}
ここで、次のように言います。
x2.N();
Y
コンソールに表示されます。これは、 のランタイムタイプが であるためx2
ですY
。
これらはすべて、人々がポリモーフィズムについて話すときの意味の一部です。
2 つのコンストラクターを使用してオブジェクトを作成することは合法ですか?
このステートメントには 2 つのコンストラクターはありません。
X x2 = new Y();
コンストラクターは 1 つだけです。左辺は変数宣言です。x2
typeという名前の変数を宣言していますX
。右側はコンストラクターの呼び出しです。Y
;のパラメーターなしのパブリック コンストラクターを呼び出しています。これにより、 の新しいインスタンスが作成されますY
。ステートメント全体が代入ステートメントです。右側の結果を左側の変数に代入しています。Y
すべての s はポリモーフィックにもX
s であるため、代入は正当ですY extends X
。