継承について - メンバの型と考え方の法則

このQ&Aのポイント
  • 継承において、フィールドの型やメソッドの実行結果の型は、その変数やオブジェクトの型ではなく、宣言された型(親クラス)に従うという法則があります。
  • 問題1では、親クラスのフィールドとメソッドをサブクラスが継承しています。そこで、変数の型に従ってdの値が10になり、メソッドの実行結果の型に従ってdの値が20.0になります。
  • 問題2では、親クラスとサブクラスのフィールドとメソッドが両方ともstatic(クラス変数やクラスメソッド)となっています。そのため、変数dやメソッドmethは親クラスのものが使用され、結果として10が出力されます。
回答を見る
  • ベストアンサー

継承について

以下のような問題(SJC-P試験)があり、 解説では考え方として ●メンバがフィールドなら「変数の型」 ●インスタンスメソッドなら「実際のオブジェクトの型」 ●クラスメソッドなら「変数の型」 とありました。 できればなぜこのような考え方(法則)になるか理解したいと思っています。 #当方、Javaプログラミング経験ゼロで、実際に下記のようなコーディングをするかどうかもわかりませんが、 #丸暗記だと実際のコーディングで使えそうにないので、できれば理解したいと思ってます。 下記問題は解説の考え方さえ丸暗記すれば解けるのかもしれませんが (なぜ解説のような考え方になるのか含め)教えていただけませんでしょうか。 ----- 【問題1】 class Super{  int d = 10;  void meth()System.out.println(d); } class Sub extends Super{  double d = 20.0;  void meth()System.out.println(d); } class Sample1{  public static void main(String[] args){  Super s = new Sub();  System.out.println(s.d);  s.meth(); } 【答え】 10 20.0 ----- 【問題2】 class Super{  static int d = 10;  static void meth()System.out.println(d); } class Sub extends Super{  static double d = 20.0;  static void meth()System.out.println(d); } class Sample2{  public static void main(String[] args){  Super s = new Sub();  System.out.println(s.d);  s.meth(); } 【答え】 10 10 ----- よろしくお願い致します。

  • kutu
  • お礼率54% (152/279)
  • Java
  • 回答数1
  • ありがとう数1

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

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

う~~ん、これってなかなか難しいですよね。 こういう動作をするように(JAVAでは)なってるとしか言いようがないような気がしますが、一応説明を試みてみます。 今スーパークラスと、そのサブクラスがあって、 同じフィールド名、同じメソッド名があるとすると、 サブクラスでは、上位クラスのフィールドやメソッドはオーバーライド(上書)されて、それぞれのクラスのモノが使われるというのは良いですよね。 今問題となっているのは、スーパークラスの変数にサブクラスの変数を入れた場合どうなるか? ということなんですが、 スーパークラスからは、スーパークラスのメソッドやフィールドにしかアクセスできないというのは良いですか? このルールで言うと、例外となるのは、質問文の問題でいうと、インスタンスメソッドがスーパークラスに代入(やキャスト)したのに、どうして、スーパークラスのメソッドが使われないで、サブクラス自身のメソッドが使われるのかということですね。 言語の実装としては、スーパークラスのメソッドが使われるような実装もありだと思いますが、そのようになっていないのは、スーパークラス変数にサブクラスの変数を代入して使うということがどういうこと(どういうことであって欲しい)かということだと思います。 スーパークラスの変数には、その配下となるさまざまなサブクラスの変数を代入できますが、そのようにするのは、それぞれのサブクラスをまとめて扱いたいからです。その時に、せっかくそれぞれの特殊化したメソッドでなくて、スーパークラスのメソッドしか使われないのであれば、何をやってんだかわからないです。つまり、変数に対して同じメソッドを使って、それぞれの特殊化した(サブクラスで定義された)メソッドを使って欲しいわけです。 まあ、そういうわけで、スーパークラス変数に代入したサブクラス変数のインスタンスメソッドが呼ばれます。 staticメソッドについては、staticメソッドは、インスタンスから呼び出しができますが、インスタンスが無くても呼び出せるクラスに固有のメソッドです。(クラスメソッド)なので、そのクラスのメソッドが呼び出されるのは、妥当です。

kutu
質問者

お礼

BLUEPIXYさん、いつもありがとうございます。 >そのようになっていないのは、スーパークラス変数にサブクラスの変数を代入して使うということがどういうこと(どういうことであって欲しい)かということだと思います。 このような考え方が私には出来ていませんでした。たしかにその通りですね。 書いていただいた事を何回も読み返してようやく理解できるようになりました。何だか喉の痞えが取れた気がします。 単なるJavaの決め事として丸暗記するのではなく、理由を納得できてよかったです。 まだSJC-P試験勉強の序盤戦。 今後もまだまだ???という部分に出会い、質問させていただくかもしれませんが、よろしくお願いします。

関連するQ&A

  • newの基本的な使い方が理解できていません

    以下のソースコードで【Super s = new Sub();】となっているのですが、これはSuperを見ているのでしょうか?またはSubでしょうか? この考え方がいまいち理解できません。 次の【System.out.println(s.d);】では、class Superの10を返しているようですが、その次の行でのs.meth(); ではclass Subの20を返しているようです。 また、クラスsuperのint dおよび、boid meth()をstaticにすると、そちらをみているようなのですが、混乱して理解できません。 すみませんが、どのようになっているか教えて頂けませんでしょうか? class Super{ int d = 10; void meth(){ System.out.println(d); } } class Sub extends Super{ double d =20.0; void math (){ System.out.println(d); } } class Test{ public static void main(String args[]){ Super s = new Sub(); System.out.println(s.d); s.meth(); } }

    • ベストアンサー
    • Java
  • 継承とオーバーライド

    サブクラスのインスタンスを、スーパークラスの変数に代入するときの考え方が分かりません。下記のプログラムを実行すると x: 10 Sub という結果にります。 spで、message()を呼び出してるのだから、Superクラスのmessage()が処理されるのではないでしょうか? また、コメントアウトすると、コンパイルエラーになる理由もわかりません。 上記の答えのように、Subクラスのmessage()を参照できるのでしたら、printY()も参照できるんじゃないのかって思います。 基本的な質問かもしれませんが、よろしくお願いします。 class Super{ int x = 10; void printX(){ System.out.println("x:" + x); } void message(){ System.out.println("Super"); } } class Sub extends Super{ int y; void printY(){ System.out.println("Y:" +y ); } void message(){ System.out.println("Sub"); } } class ExtensSample01{ public static void main(String[] args){ Super sp = new Sub(); sp.printX(); // sp.printY(); sp. message(); } }

    • ベストアンサー
    • Java
  • javaの質問です。

    明日JavaのBronze試験を受けに行くのですが、全然わからずに困っています。 紫色のJavaプログラマBronzr[SE7]という本を使用しています。 本の模試の問題です。 37 Class Super{ static void method(){ System.out.println("Super"); } } Class Sub extends Super{ static void method(){ System.out.println("Sub"); } } Class Test { public static void main(String[] args){ Super obj = new Sub(); obj.method(); } } この問題はSuperが表示されるらしいのですが、理由がわかりません。 サブクラスをインスタンス化しているので、Subが表示されるというのなら理解できます。staticが関係あるのはなんとなくわかるのですが、、、、、、なぜSuperなのかがわかりません。 解答ではスーパークラスの型にサブクラスを入れているからと簡単に書いてあります。 詳しく説明していただけると助かります。

    • ベストアンサー
    • Java
  • abstract と static を一緒に付けることはある?

    抽象クラスの抽象メソッドにstaticを付ける(abstract と static をメソッドに一緒に付ける)ことはありますか? 例えば、 abstract class Super {  static abstract void meth(); } class Sub extends Super {  static void meth() {   System.out.print("hello");  } } として、mainの中に  Sub.meth(); を書いてみたのですが、普通にコンパイルは通りhelloが出力されます。 staticの意味を考えると、こういうことをするのは意味がないと思うのですが、独学なので身近に聞ける人もいません。 御教授よろしくお願いします。

  • Exceptionクラスの継承について

    Exceptionクラスを継承しているExceptionMがありますが、その中にsuper(message)というものがあります。 これは、スーパークラスのExceptionがmessageという変数を引数で受けることができるメソッドを使用していることは分かりますが、実際何を行っているのでしょうか? そして、この処理によって何を得ているのでしょうか? あと、try{のなかにtry{という変な記述していますが、問題でそうかかれていただけなので気にしないでください。 問題箇所 class ExceptionM extends Exception{ public ExceptionM(String message){ super(message); } } 全ソース class ExceptionSubclassQuestion{ public static void main(String args[]){ a(); } static void a(){ try{ try{ throw new ExceptionM("M"); }catch(ExceptionN e){ System.out.println("lnner catch"); e.printStackTrace(); } }catch(ExceptionM e){ System.out.println("Quter catch"); e.printStackTrace(); } } } class ExceptionM extends Exception{ public ExceptionM(String message){ super(message); } } class ExceptionN extends ExceptionM{ public ExceptionN(String message){ super(message); } }

    • ベストアンサー
    • Java
  • mainクラスのpublicの意味を教えて下さい

     お早う御座います、JAVA初心者です、宜しくお願いします。  main クラスの public をコメントアウトしてもエラーもなく走ります。  これは、「public static void main(String[] args)」を持っているクラスを自動的に「main クラス」と判断しているということでしょうか。 ============================================================ class Sub { void disp() { System.out.println(" a "); } } /*public*/ class Main { public static void main(String[] args) { Sub s = new Sub(); s.disp(); } }

    • ベストアンサー
    • Java
  • クラス変数/メソッドとインスタンス変数/メソッドの見え方について

    Javaの言語仕様(?)についてお教え下さい。 参照変数の型がインスタンスのスーパークラスの型の時、クラス変数/メソッドとインスタンス変数/メソッドの見え方が納得いかずに困っています。 以下のような条件の時です。   ・クラスが2つあり、1つはもう1つのクラスを継承しています。     それぞれを「スーパー」「サブ」と以下で呼びます。   ・インスタンスは"サブ"の型です。   ・上記インスタンスへの参照変数は"スーパー"のクラスの型です。   ・"スーパー"、"サブ"ともに【同名】の「クラス」変数/メソッド、「インスタンス」変数/メソッドがあります。 この場合に、"サブ"のインスタンスを参照している"スーパー"の型の変数を介し、それらにアクセスしたらどれが見えるか?という疑問です。 実験結果では以下のようになりました。           [フィールド]  [メソッド]   [1.static ]  スーパーの   スーパーの   [2.非static]  スーパーの   サブの 納得いかないのは「2.非static」で「フィールド」が、「スーパーの」になるところです。 これも「サブの」になると思っていました。 なぜサブクラスのが見えないのでしょうか? 同名の変数なのでスーパークラスのはサブクラスので隠れされ、サブクラスのが見えると思っていたのですが。 参考書には以下のように書いてありました。   フィールドの場合、参照変数の型のものが見える。   メソッドの場合、インスタンスの型のものが見える。 私には不自然に感じられるのですが、「こういう仕様だから。」と納得するしか無いのでしょうか? 「なぜこうなるか」について説明がある文献、サイトなどありましたらお教えください。 参考までに以下が実験したサンプルコードと結果です。長くて申し訳ありません。 「サンプルコード」 public class Super { static int staticField = 10; int instanceField = 100; static void staticMethod() { System.out.println( "staticField = " + staticField ); } void instanceMethod() { System.out.println( "instanceField = " + instanceField ); } } public class Sub extends Super { static int staticField = 90; int instanceField = 900; static void staticMethod() { System.out.println( "staticField = " + staticField ); } void instanceMethod() { System.out.println( "instanceField = " + instanceField ); } } public class TestStatic { public static void main(String[] args) { // インスタンスはSub、参照変数もSub、という状態。 Sub sub = new Sub(); System.out.println( "実験1" ); System.out.println( "1.クラス変数      " + sub.staticField ); System.out.print( "2.クラスメソッド    " ); sub.staticMethod(); System.out.println( "3.インスタンス変数   " + sub.instanceField ); System.out.print( "4.インスタンスメソッド " ); sub.instanceMethod(); // インスタンスはSub、参照変数はSuper、という状態。 Super sup = new Sub(); System.out.println( "実験2" ); System.out.println( "5.クラス変数      " + sup.staticField ); System.out.print( "6.クラスメソッド    " ); sup.staticMethod(); System.out.println( "7.インスタンス変数   " + sup.instanceField ); System.out.print( "8.インスタンスメソッド " ); sup.instanceMethod(); } } 「結果」 実験1 1.クラス変数      90 2.クラスメソッド    staticField = 90 3.インスタンス変数   900 4.インスタンスメソッド instanceField = 900 実験2 5.クラス変数      10 6.クラスメソッド    staticField = 10 7.インスタンス変数   100 8.インスタンスメソッド instanceField = 900 納得が行かないのは7のところです。 以上よろしくお願いいたします。

    • ベストアンサー
    • Java
  • 抽象クラス について

    obj.write();した時 class super1 の write()が呼ばれ その後 class HINA の write()が呼ばるのか? 直接 class HINA の write()が呼ばるのか? どう呼び出してるのか 教えてください abstract class super1 { abstract void write(); } class HINA extends super1{ void write() { System.out.println( "LOVE HINA" ); } } class test { public static void main( String args[] ) { super1 obj = new HINA(); obj.write(); } } }

  • Javaのコンストラクタについて教えてください

    Javaを勉強している初心者です。 次のようなプログラムがあります。 このプログラムでclass aおよびclass bのデフォルトコンストラクタ a() {}とb() {}をコーディングしていないとコンパイルエラーになります。 b() {}についてはclass bのパラメータのあるコンストラクタb(String s)がサブクラスclass cから明示的に呼ばれていないのでデフォルトコンストラクタb() {}をコーディングしないとエラーになる…と考えればよいのでしょうか。 それでは、a() {}はなぜ必要なのでしょうか。 どなたか教えてください。 class a { a() {} a(String s) { System.out.println("In a's constructor..."); System.out.println(s); } } class b extends a { b() {} b(String s) { super(s); System.out.println("In b's constructor..."); System.out.println(s); } } class c extends b { c(String s) { System.out.println("In c's constructor..."); System.out.println(s); } public void some() { System.out.println("something..."); } } public class appJ01 { public static void main(String args[]) { c obj = new c("Hello from Java!"); } } 

  • オーバーロードの「あいまい」エラーについて

    お世話になっております。 メソッドのオーバーロードにおいて、以下の様な場合にコンパイルエラーが発生します。 環境:JDK1.6.0_13 + eclipse3.3.2 public class Sample { static void meth(long... longs){ System.out.println("long..."); } static void meth(Integer... Integers) { System.out.println("Integer..."); } public static void main(String[] args){ meth(100); } } エラーメッセージ:メソッド meth(long[]) は型 Sample であいまいです (以下、「あいまいエラー」と表記します) 今回のケースでは、なぜこの様なエラーが出てしまうのか、今一つわからずに困っています。 「あいまいエラー」について少し調べを入れてみましたが、 参照型を引数に取るメソッドが複数ある時にnullを渡した時など、 明瞭にわかりやすいケースの例示は見つかったのですが、 今回の様なケースに当てはめて納得の行く情報ソースは見つけられませんでした。 まとめますと、私の欲しい情報は、 可変長引数リストを引数に取るオーバーロードメソッドが複数ある時に、 「あいまいエラー」が発生する規則です。 以上です。よろしくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう