スーパークラスとサブクラスについて

このQ&Aのポイント
  • スーパークラスとサブクラスの関係について説明します。
  • ParentクラスとChildrenクラスを使った例を通して、pcオブジェクトの性質について説明します。
  • pcオブジェクトはChildrenクラスのインスタンスであり、Parentクラスのメソッドを実行することができますが、Childrenクラスのメソッドは実行できません。
回答を見る
  • ベストアンサー

スーパークラスとサブクラスについて

Parent pc = new Children(); pc.getName(); 下記、2つのクラスがある状態で上記のようにしてgetName()を実行したところ サブクラスのgetName()が呼ばれました。このことからpcオブジェクトの実態はChildrenクラス なのだと理解していたのですが、サブクラスにしか存在しないメソッドを呼ぼうとして pc.getChildName()と記述したところコンパイルエラーになってしまいました。 pc.getParentName()となら記述することができるのですがpcオブジェクトのをどう理解すれば よいのでしょうか。 【親クラス】 public class Parent { public void getName() { System.out.println("Parent"); } public void getParentName() { System.out.println("親クラス特有のメソッド"); } } 【サブクラス】 public class Children extends Parent{ @Override public void getName() { System.out.println("Children"); } public void getChildName() { System.out.println("サブクラス特有のメソッド"); } }

  • Java
  • 回答数3
  • ありがとう数6

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

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.3

 Parent pc = ほにゃらら; と書いたとき、pc の実態がどうであれ pc は Parent としてふるまうことを要求されます。 つまりあなたも理解している通り、Parent を継承した Child に追加されたメソッドやプロパティは Parent に存在しないため利用できません。 しかし、要求されるのはメソッドの外から見た振る舞い(引数の数、各引数の型、戻り値の型)だけで、内部の処理まで同一であることは要求されません。 オーバーライドは和訳すると「決定などを覆す」という意味があります。 その意味通りに親クラスの処理内容を覆して別の処理にするのがオーバーライドという機構で、サブクラスの処理に切り替わらなくてはオーバーライドさせる意味がありません。 ですから、 > 同名のメソッド(オーバーライドされたメソッド)が親クラスにもサブクラスにも存在した場合、 > pc.getName()ではサブクラスのメソッドが呼ばれるというのがどうも腑に落ちないところです。 と言われても、オーバーライドとはそういうものだと飲み込んでもらうしかありません。 この辺りは言語仕様でそうなっているというよりはオブジェクト指向の特徴の一つである「多態性」を実現するためにそうなっていると思ってください。

unko347
質問者

お礼

>>オーバーライドは和訳すると「決定などを覆す」という意味があります。 そんな意味があったのですね。これでしっくりきました。 決定を覆してオーバーライドされたものを実行するのですね。ご回答ありがとうございました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「文法的に」というかなんというか. Parent 型の変数には「Parent クラスから派生した任意のクラスのオブジェクト」を入れることができる. あたりまえだけど, その「Parent クラスから (以下省略)」のオブジェクトとして「Parent クラスのオブジェクト」をとることもできる. でも, Parent クラスのオブジェクトに対して「Children クラスにしかないメソッド」は呼び出せないでしょ?

unko347
質問者

補足

Parent pc = new Children(); pc.getName(); とあったときpcオブジェクトはParentクラスのオブジェクト なのでChildrenクラスにしかないメソッドが呼べないのは わかるのですが同名のメソッド(オーバーライドされた メソッド)が親クラスにもサブクラスにも存在した場合、 pc.getName()ではサブクラスのメソッドが呼ばれると いうのがどうも腑に落ちないところです。

  • notnot
  • ベストアンサー率47% (4847/10258)
回答No.1

変数pcはParentクラス型なので、Parentクラスにないメソッドは呼べません。 ParentクラスとChildrenクラスの両方にある同名のメソッドのどちらが呼ばれるかは、pcに格納されているオブジェクトのクラスによります。new Parent()で作ったものか、new Children() で作った物かによって違う。 Childrenクラスにしかないメソッドを呼ぶには、そのオブジェクトをChildrenクラス型の変数に格納する必要があります。

unko347
質問者

補足

ご回答ありがとうございます。 文法的にそういうものなんですね。 頭に叩き込みたいと思います。

関連するQ&A

  • javaプログラムのクラス図など

    「下記のプログラム例のクラス図を描き、プログラム例にはクラス図に対応するブロックにブロックコメントを挿入しなさい。最後にプログラム例でオブジェクト指向の三大要素がどのように実現されているかを説明してください。」 の部分が3週間自分なりに調べたりしたのですが全く分からなく このように質問している恥ずかしい状況です(>_<) 正直言って、明日までの課題です。。。 人生がかかっている言うと大袈裟に聞こえるかもしれないんですが 正直その通りなんです。。。 お力添えしていただける方を探しています。 どうか、お助けください。。。。。。 問題 オブジェクト指向の三大要素についてまとめなさい。次に、下記のプログラム例のクラス図を描き、プログラム例にはクラス図に対応するブロックにブロックコメントを挿入しなさい。最後にプログラム例でオブジェクト指向の三大要素がどのように実現されているかを説明してください。 Animalインタフェース public interface Animal { public abstract void bark(); } ーーーーーーーーーーーーーーー Petインタフェース public interface Pet extends Animal { public String getName(); } ーーーーーーーーーーーーーーー Catクラス class Cat implements Pet { private String name; public Cat(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void bark() { System.out.println("ね こ:ニャー"); } } ーーーーーーーーーーーーーーー Dogクラス class Dog implements Pet { private String name; public Dog(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void bark() { System.out.println("い ぬ:ワン"); } } ーーーーーーーーーーーーーーーー Duckクラス class Duck implements Pet { private String name; public Duck(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void bark() { System.out.println("あひる:ガーガー"); } } ーーーーーーーーーーーーーーーー Frogクラス class Frog implements Pet { private String name; public Frog(String name) { this.name = name; } @Override public String getName() { return name; } @Override public void bark() { System.out.println("かえる:ケロケロ"); } } ーーーーーーーーーーーーーーーー PetTestクラス public class PetTest { public static void main (String[] args) { Pet[] pets = {new Cat("タロー"), new Dog("ミケ"), new Frog("ケロ"), new Duck("ドナルド") }; System.out.println(); for(Pet pet: pets) { System.out.printf("\t%8s\t", pet.getName()); pet.bark(); } System.out.println(); } } ーーーーーーーーーーーーーーーーーー 実行結果がこうなります D:\Work >java PetTest タロー ね こ:ニャー ミケ い ぬ:ワン ケロ かえる:ケロケロ ドナルド あひる:ガーガー -- Press any key to exit (Input "c" to continue) -- 上の問題なのですが もし解くことができる方がいましたら お願いします_(._.)_

  • スーパークラスからサブクラスのメソッドを使おうとする、以下のプログラム

    スーパークラスからサブクラスのメソッドを使おうとする、以下のプログラムでつまずいています。 Aを継承したB、Cクラスのインスタンスを作成し、スーパークラスであるA型の配列asにまとめます。 それからループでas[i]にはいっている各インスタンスのメソッドを使いたいのですが、 スーパークラスAにmethod()がないためコンパイルできません、Aにmethod()を作るとA.method()が実行されます。 BとCを同じ配列に保存し、かつそれぞれのmethod()を実行したい場合どのようにしたら良いのでしょうか。 ご教授ください、どうぞよろしくお願いします。 class Main{ private B b; private C c; private A[] as = new A[2]; void mainMethod(){ as[0] = b = new B(); as[1] = c = new C(); for(int i=0; i<3; i++){ as[i].method(); } } } class A{} class B extends A{ void method(){ System.out.print("It is B"); } } class C extends A{ void method(){ System.out.print("It is C"); } }

  • サブクラス型オブジェクトをスーパークラス方に代入

    ある所で下記のような継承についての記述をみつけました。 ----------------------------------------------------------------------------- 継承の目的は、あるクラスで実装したメソッドなどの機能を利用して、 さらに実装を追加する差分コーディングです。 一つのクラスから複数のサブクラスを作ることも良くあります。 このような時、それらのサブクラス型オブジェクトの参照を代入できる変数として、 スーパークラス型変数を使うことがしばしばあります。 ----------------------------------------------------------------------------- サブクラス型オブジェクトの参照を代入できる変数として、 スーパークラス型変数を使うことがある、と いうのはどういった場合に使うのでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 実行中のメソッド名

    お世話になります。 実行中のメソッド名を取得することってできますか? public void methodA(){ System.out.println(□□□+"というメソッドが呼ばれました"); } の□□□になにをいれたらよいでしょうか? クラス名は取れる(this.class.getClass().getName())のですが実行中のメソッドってとれないのでしょうか? 以上よろしくお願い致します。

    • ベストアンサー
    • 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
  • PHPでサブクラスからスーパクラスのprivate

    メンバにアクセスできる件について PHPでスーパークラスで定義したprivateのメンバにサブクラスからアクセスできる件について 質問です。 class TestClass { private $value01 = "スーパークラスの private メンバ"; public function testMethod01 () { print "スーパークラスのパブリックメソッド"; print "<h1>{$this->value01}</h1>"; } protected function testMethod02(){ print "スーパークラスの protected メソッド"; } private function testMethod03(){ print "スーパークラスの private メソッド"; } public function getMethodList(){ print_r(get_class_methods($this)); } } class ExClass extends TestClass{ private $value01 = "サブクラスの private メンバ"; } $obj = new ExClass(); $obj-> testMethod01(); と上記のようにサブクラスのインスタンスから継承したpublicなメソッド testMethod01()を実行すると スーパークラスのprivateなプロパティにアクセスできてしまいます。 これってどういうことでしょうか?privateメンバってそのクラスの中からだけしかアクセスできませんよね? 上記では、サブクラスからアクセスしているような状態にみえますがどういうことでしょうか? ご教授御願い致します。

    • ベストアンサー
    • PHP
  • クラス名

    JAVAの初心者です。 今実行しているクラスのクラス名を求めたいのですが うまくいかず困っております。 public class Person {   public static void main(String args[]);   {     String classname;     classname = this.class.getClass().getName();     System.out.println(classname);   } } イメージ的にはこんな感じなのかなと思ってやってみたのですが、 どうやら違うみたいです。どうぞご教授よろしくおねがいします。

    • ベストアンサー
    • Java
  • C# と Javaの継承の違い

    http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_004/csharp_abc02.html 上記、URLの記事にて Person someone = new Taro();  → TaroはPersonのサブクラス Console.WriteLine( someone.getName() ); という記述がありgetName()の結果はPersonクラスのgetName()が表示されるとなっていました。 同様のことをJavaにて試してみたところ Parent pc = new Children(); → ChildrenはParentのサブクラス pc.getName(); getName()にはChildrenクラスのgetName()が表示されました。 C#とJavaでは継承の挙動に違いがあるのでしょうか。

  • サブクラスでセッターを呼び出す

    java初心者です。 以下のようなソースコードで、コンパイルしたらエラーが出ました。 サブクラスのsetterのところでエラーが出たんですが、 サブクラスでスーパークラスのメソッドは呼び出せないんでしょうか? それとも他に間違いがあるんでしょうか? class rensyu { private int x; rensyu(){ x=this.x; } int getX(){ return x; } void setX(int m){ this.x = m; } } class rensyu2 extends rensyu{ private rensyu[] A; rensyu2(){ A = new rensyu[100]; } int getter(int i){ return A[i].getX(); } void setter(int x,int i){ A[i].setX(x); } } class rensyuTester{ public static void main(String[] args) { rensyu2 A = new rensyu2(); A.setter(1,0); A.setter(2,1); System.out.println(A.getter(0) +" "+ A.getter(1)); } }

    • ベストアンサー
    • Java
  • ArrayクラスとtoStringについて

    問題集で次のプログラムを見掛ました。 public class Main{  public static void main(String args[]){   int[] array = new int[0];   System.out.println(array);  } } これを実行するとprintlnメソッドで toStringメソッドが呼び出されますが、 ArrayクラスはObjectクラスを継承しているため、 toStringメソッドもObjectクラスから継承されているので、 結果として、配列の要素数が0であっても、 エラー等が発生せずハッシュコードが表示される、ということです。 ObjectクラスのtoStringメソッドが ハッシュコードを返すものであるのは理解できます。 でも、なぜ要素数が1以上で何かしらの要素が存在する場合は、 ハッシュコードが返らないのでしょうか? 詳しい方、解説をお願いします。

専門家に質問してみよう