• ベストアンサー

親クラスの型で子のオブジェクトを扱う

●下記のコードについての質問となります class Y { int num2 = 20; } class Z extends Y { int num3 = 30; } class Sample{ public static void main(String args[]){ --------------------------------------------- Y y1 = new Z(); --------------------------------------------- System.out.println(y1.num2); System.out.println(y1.num3); } } 「-----」で囲まれている部分になりますが、 親クラスの型で子のオブジェクトを扱おうと思うのですが、 「System.out.println(y1.num3);」 この部分において、コンパイルエラーとなります。 Zクラスから生成されたオブジェクトへの参照を Y型変数y1に代入していると思うのですが、 何故、「y1.num3」の値が表示されないのかを ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ お伺いしたいと思っております。 以上、宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
noname#24040
noname#24040
回答No.3

スーパークラス型参照のオブジェクトからは、サブクラスの変数やメソッドにアクセスできません。 コンパイラーがはじきます。 この話にはつづきがありまして、、、余談ですが、 Y y1 = new Z(); スーパークラスY、サブクラスZ Z IS-A Y という関係(IS-A関係)が成り立ちます。 このときは、メソッドに関しては、 スーパークラスのメソッドをサブクラスでオーバーライドした場合、 スーパークラス型参照のオブジェクトからサブクラスのメソッド(オーバーライドされたメソッド)にアクセスできます。 これが「ポリモーフィズム」です。 あくまで参考です(おせっかいでしたらすみません)

KGM
質問者

お礼

説明ありがとうございます。 このような、解答があると便利になります。 多態性のことを考えると、納得いくようなきがします。

その他の回答 (2)

noname#58274
noname#58274
回答No.2

Y y1 と宣言した時点で、y1はあくまでYクラス扱いになります。 つまり、Yから派生したクラスを参照しているかもしれませんが、派生しているかどうかはy1という変数では意識しません。 逆に意識しなくて良い事が、ポリモーフィズム的に意味を持ちます。 コンパイルエラーの判定は、その変数でその意識をしているかどうかで行われるので、上記Yクラス扱いになっているので、エラーになります。

KGM
質問者

お礼

説明ありがとうございます。 多態性を考えると、納得がいきますね^^ 感謝感激です。

  • unibon
  • ベストアンサー率47% (160/340)
回答No.1

> Zクラスから生成されたオブジェクトへの参照を > Y型変数y1に代入していると思うのですが、 > > 何故、「y1.num3」の値が表示されないのかを たとえば「Xクラス」もあったとします。 class X extends Y { int num4 = 30; } この場合、「Y型変数y1」でアクセスしている限り、その変数(y1)に「Zクラス」のインスタンスが入っているか、はたまた「Xクラス」のインスタンスが入っているかコンパイル時には分かりません。実行時になって初めて分かります。だからコンパイルエラーにするのです。 なお、Java 以外の言語を考えた場合、言語の作りによっては、こういう場合にコンパイルエラーにしないというやりかたも考えられなくはありません。しかしこうすると、num3 であろうが num4 であろうが num5 であろうが、全部コンパイルを通すことにせざるを得ません。もし間違って nun3 のように変数名を間違っていてもコンパイルエラーにならないわけです。これでは型やクラスの意味がなくなってしまいます。だから普通の言語ではこういうのはコンパイル時にエラーにします。

関連するQ&A