• ベストアンサー

オーバーライドの必要性

まだまだJavaを勉強している途中なのですが、下記のサンプルコードでオーバーライド(メソッドをオーバーロードすることをオーバーライドというのでしょうか…!?)のの必要性がよく分からなくなってしまったので質問させて頂きました。 /* sample.java */ abstract class super_class{  void write(){} } class CLASS1 extends super_class{  void write(){ System.out.println("CLASS1"); } } class CLASS2 extends super_class{  void write(){ System.out.println("CLASS2"); } } class sample{  public static void main(String args[]){   super_class obj = new CLASS2();   obj.write();   obj = new CLASS1();   obj.write();  } } 以上のコードを実行した場合 CLASS2 CLASS1 と表示されるのは多少なりとも勉強して分かったつもりでした…。 しかし、あくまでサンプルであるために特に意味がないことでもオーバーライドの説明をしているのだろうという風に考えてしまったのですが、 結局は、 スーパークラスとサブクラスに同じシグネチャのメソッドがあった場合、各サブクラスのメソッドが実行される と言うことは、スーパークラスのwrite()メソッドは何をしているのでしょうか? 多様性はJavaでも大切なものであるとのことなので質問させて頂きました。 なるべくわかりやすく説明して頂きたいと思います。 どうかお答えをお願いします。

  • ryo-3
  • お礼率64% (146/226)
  • Java
  • 回答数3
  • ありがとう数7

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

  • ベストアンサー
  • nontatta
  • ベストアンサー率34% (18/52)
回答No.2

度々すみません。追記です。 オーバーライドをするメリットについて、先の回答では、乗り物クラスの各サブクラスが勝手に自由に、乗り物を走らせるメソッドを定義すると管理しにくくなる、とだけお話しました。これに関して、もう1つの理由として、以下のことが挙げられるでしょう。 たとえは同じく、乗り物クラスとそれを継承するサブクラスです。 例えば、あるプログラムの処理で、乗り物クラスを継承した任意のサブクラスのオブジェクトが外部から渡されるとします。この時、そのオブジェクトはどのクラスオブジェクトであるかは不明(自動車クラスだか自転車クラスだか飛行機クラスだかは不明)です。その、自動車オブジェクトだか自転車オブジェクトだか飛行機オブジェクトだか何だか分からないけど、とにかくその乗り物を走らせたい、という処理が必要になるとします。このとき、それぞれのサブクラスで、乗り物を走らせるためのメソッドがばらばらに定義されていると、上記の、「なんだかわからないけど走らせたい」という処理は不可能になります。 スーパークラスで戻り値も引数もメソッド名も全て同じ「走る」抽象メソッドを用意することで、実際のプログラムでは、その何だか分からないオブジェクトのメソッドにスーパーで定義された引数を渡せば、以上の要件(何だか分からないオブジェクトを走らせること)が満たされます。

ryo-3
質問者

お礼

なるほど・・・ 「使わないといけない」という風に考えると前よりはずいぶんと分かりました。 これからまだ勉強してオーバーライドのありがたみを感じたいと思います。笑 お答えありがとうございました。

その他の回答 (2)

  • chi-kon
  • ベストアンサー率43% (58/132)
回答No.3

Sampleクラスで各インスタンスをnewしているからメリットがわからないかもしれませんね。 車というスーパークラスとセダンクラス、トラッククラス、車工場というクラスを使うとメリットがわかるかもしれません。 車工場{ public static 車 get車(String 種類){ if(種類.equals("セダン")){ return new セダン(); }else if(種類.equals("トラック")){ return new トラック(); }else{ return null; } } } ってあったときに class Sample{ 車 car = 車工場.get車("セダン"); car.write(); } のようなつくりにした場合、 Sampleクラスは車を受け取るのはわかっていますが、 どんな車がどうやって製造されるかをしらなくても くるまとしてつかうことができます。 しかも車の種類が増えたとしても 車クラスのサブクラスであるかぎりSampleクラスは変更をうけません。 適当な説明になりましたが、なにかのヒントになれば幸いです。

ryo-3
質問者

お礼

やっぱりJavaは理解をしていないとなかなか難しいですね・・・ 中身を知らなくても動くっていうのはいいとは思います。 どうもありがとうございました。

  • nontatta
  • ベストアンサー率34% (18/52)
回答No.1

こんにちは(^ー^) まず、オーバーライドとオーバーロードは別物です。 オーバーライドは、スーパークラスで定義された実際の処理内容は未定のメソッドをサブクラスで実装(実際の処理内容を記述する)ことです。 オーバーロードは、引数が異なる同じメソッドを複数定義することです。例えば、StringクラスのvalueOfメソッドは、引数の文字列表現を返すメソッドです。ここで、引数には色々な型の値を渡すことが出来ます。例えば、int型の数値を引数に引数に与えれば、その数値の文字列表現を返します。同様に、double型の数値を渡してもその文字列表現、long型の数値を渡してもその文字列表現が返ってきます。これは、実際にはStringクラスに引数の異なる同じvalueOfメソッドが何個も何個も定義されていることにより可能となっています。使っている側にとって、引数にいろいろな型の値を渡せることは大変便利です。これがオーバーロードです。 次に、本題のオーバーライドについてですが、ご質問にあるスーパークラスがabstract修飾子のついた抽象クラスである点を踏まえてお話します。 例えば、乗り物クラスがあったとします。この乗り物クラスを自動車クラス、自転車クラス、オートバイクラス、飛行機クラス等が継承するとします。 まず、スーパークラスである乗り物クラスには、それを継承するどのサブクラスにも共通の、乗り物を動かすための「走る」メソッドが用意されているとします。 しかし、実際に、どうやってその乗り物を走らせるのか、という処理内容については、乗り物クラスを継承する各サブクラスによって異なります。たとえば、自動車クラスでは、エンジンをかけ、アクセルを踏むという処理が必要になります。自転車クラスでは、ペダルに足を乗せ、キコキコペダルを回すという処理が必要になります。つまり、乗り物クラスには、どれも「走る」メソッドが必要なのですが、その処理内容が異なるため、スーパークラスで「走る」メソッドの定義だけ提供し、継承するサブクラスで実際の処理内容を記述するわけです。 だったら、スーパーの乗り物クラスでわざわざ「走る」メソッドなんか定義しなくたって、サブクラスで勝手に定義しちゃえばいいじゃないか、ともいえますが、これはオブジェクト指向に反した考えでしょう。また、ある程度大きなシステムになってくると不都合が生じます。各サブクラスで個別に自由に定義するとすると、例えば、同じ「走る」メソッドについて、自動車クラスを作る人は「運転」メソッドを定義するかもしれません。また、自転車クラスを作る人は、「自転車をこぐ」メソッドを作るかもしれません。こうすると、全体でシステムを眺めたときに、大変管理しずらくなります。そこでまずスーパーの乗り物クラス抽象クラスで定義し、これを継承する全てのサブクラスは必ずクラス内で定義されている「走る」メソッドを実装しなければいけなくします。そして、それを継承するサブクラスで「走る」メソッドについてそれぞれの処理内容を記述すれば、そのシステムについて何も知らない人でも、スーパークラスの「乗り物」クラスを見れば、ああ、これを継承するサブクラスにはみんな必ず「走る」メソッドがあるんだなぁ、と分かりやすくなります。これは1つの側面です。 また、自動車や自転車、飛行機等の乗り物クラスのサブクラスでは、「座席に座る」メソッドを実装しなければいけないとします。この「座席に座る」メソッドは、自動車だろうが、自転車だろうが、飛行機だろうが、どのサブクラスでも処理内容はまったく一緒です(ただ運転する人が座席に座るというだけの処理)。こうした場合、それぞれのサブクラスでいちいち「座席に座る」メソッドを定義するのは愚考でしょう。スーパーの乗り物クラスで、「座席に座る」メソッドを処理内容も含めて定義したほうが得策というか普通です。 話はそれますが、抽象メソッド(処理内容の記述されていないメソッド)を1つでも持つクラスは抽象クラスです。抽象クラスはインスタンス化できません。それを継承するサブクラスで初めてインスタンス化することができます。しかし、抽象クラスを継承するサブクラスが、そのスーパークラスである抽象クラスの持つ抽象メソッドを実装していることが、インスタンス化の条件となります。 上の例ですと、乗り物クラスはそれを継承するどのサブクラスでも共通の「座席に座る」メソッドと、継承するサブクラスによって処理内容の異なる「走る」メソッド(抽象メソッド)が用意されています。これを継承する自動車クラス、自転車クラス等は、「走る」メソッドを実装して初めてインスタンス化することができるようになります。 何度も同じような話で分かりづらくなってしまいましたが、なんとなく見えてきますでしょうか? 私も素人に毛が生えたようなものですので、間違った記載がありましたらすみません。どなたか精通している方の回答を待つことにしましょう。

関連するQ&A

  • メソッドのオーバーライド(java)

    class A3{ void hello(){ System.out.println("A3"); } void hello(int i){ System.out.println("A3"+i); } } class B3 extends A3{ void hello(){ System.out.println("B3"); } } class C3 extends B3{ void hello(String s){ System.out.println("C3"+s); } } class MethodOverriding3{ public static void main(String args[]){ A3 obj = new C3(); obj.hello(); } } 上のプログラムを実行すると"B3"と表示されまが、どうしてクラスBのメソッドが実行されるのでしょうか? クラスAのメソッドが無視される仕組みがわかりません。 また、クラスMethodOverriding3でobj.hello("abc")としてコンパイルすると mo.java:25: シンボルを見つけられません。 シンボル: メソッド hello(java.lang.String) 場所 : A3 の クラス obj.hello("abc");   ^ エラー 1 個 とエラーが出ます。 どうしてでしょうか? 誰か教えてください、お願いします。

    • ベストアンサー
    • 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
  • 継承とオーバーライド

    サブクラスのインスタンスを、スーパークラスの変数に代入するときの考え方が分かりません。下記のプログラムを実行すると 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のインタフェースに関する質問です。 私はこれまで、インタフェースを使うときは、インタフェースを実装してクラスを宣言し、そのクラス、またはサブクラスでインタフェースがもつすべての抽象メソッドを定義する、と理解していました。 しかし、下の例をみてください。抽象メソッドの定義を、インタフェースの実装の以前で与えています。問題無くコンパイルでき、実行できます。実行結果も以下の通りです。 インタフェースの抽象メソッドへの定義の与え方やその実行のされ方は、メソッドのオーバーライドと同様と思っていましたので、下記のコードでは「クラスBが抽象クラスではありません」や、「インタフェースの抽象メソッドがオーバーライドされていません」などの文法エラーがでると思っていました。 そこで、質問です。 インタフェースが持つ抽象メソッドの定義を与える場所について、または、これに関する説明のあるページなど、何かご存知でしたら教えてください。 ★コード★ interface X{   void show(); } class A{   public void show(){     System.out.println("A");   } } class B extends A implements X{ } public class Main{   public static void main(String[] args){     X x=new B();     x.show();   } } ★実行結果★ >java Main A ★Java環境★ java 1.6.0_21 javac 1.6.0_16

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

    こんにちは。 javaの勉強をしているのですが コンパイルエラーが発生しました。 オーバーライドのプログラムに関する質問です。 まずはプログラムなんですが class Human{ protected String name; protected int height; protected double weight; public Human(){ name = ""; height = 0; weight = 0.0; } public void setName(String n){ name = n; } public void setHeight(int h){ height = h; } public void setWeight(double w){ weight = w; } public void show(){ System.out.println(name + "の身長は" + height + "cm。体重は" + weight + "kgです。"); } } class Teacher extends Human{ private String cource; public void setCource(String c){ cource = c; } public void show(){ System.out.println("担当科目は" + course + "です。"); } } class Ex73{ public static void main(String args[]){ Student human1 = new Student(); human1.setName("一郎"); human1.setHeight(164); human1.setWeight(62.5); human1.setCourse("java"); human1.show(); } } /* Ex73.java:35: シンボルを解決できません。 シンボル: 変数 course 場所 : Teacher の クラス System.out.println("担当科目は" + course + "です。"); ^ Ex73.java:47: シンボルを解決できません。 シンボル: メソッド setCourse (java.lang.String) 場所 : Student の クラス human1.setCourse("java"); */ このプログラムは TeacherクラスでHumanクラスのshow()メソッドをオーバーライドすると言うものです。 どなたかよろしくお願いします。

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

    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
  • 抽象クラス について

    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初心者です。

    javaにおけるprivateメンバの動きについて伺いたいことがございます。 基本的にスーパークラスのprivateなメンバへはメソッド・フィールドともにサブクラスからは アクセスできないとのことですが、 例えば、以下のようなコードがあるとします。 //スーパークラスの定義 class SuperClass{ private String privateString = "スーパークラスのプライベートメンバ"; public void getter(){ System.out.println(this.privateString); } } //サブクラス class SubClass extends SuperClass{ } //実行クラス class RunClass { static public void main (String args []){ SubClass subObj; subObj = new SubClass(); subObj.getter(); } } 上記のようなコードの場合サブクラスのインスタンスであるsubObjが スーパークラスのpublicなメソッドを通じてサブクラスからスーパークラスのprivateメンバへアクセスが できてしまっています。 これは、スーパークラスのprivateが隠蔽されていないのではないでしょうか? 果たして、このときいったサブクラスのインスタンスのsubObjはどういった動きをしているのでしょうか?

    • ベストアンサー
    • Java
  • 親クラスとオーバーライドらへんのこと

    はじめまして、最近c++をはじめたものです。 質問があります。 サブクラスで親クラスのメソッドをオーバーライドした時に、 そのメソッドの中で親クラスのメソッド(オーバーライドした)をメソッドを呼び出したいのですが。 やりかたがわかりません。 要するに、javaでいうsuperを使いたいのですが。。 コードで書くとこんなかんじです。 class base { public: int abc(); } class derived : public base { public: int abc(); } int derived::abc() { super.abc() //←ここの部分がわかりません。 他の処理 }

専門家に質問してみよう