まだまだ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でも大切なものであるとのことなので質問させて頂きました。
なるべくわかりやすく説明して頂きたいと思います。
どうかお答えをお願いします。
No.2ベストアンサー
- 回答日時:
度々すみません。
追記です。オーバーライドをするメリットについて、先の回答では、乗り物クラスの各サブクラスが勝手に自由に、乗り物を走らせるメソッドを定義すると管理しにくくなる、とだけお話しました。これに関して、もう1つの理由として、以下のことが挙げられるでしょう。
たとえは同じく、乗り物クラスとそれを継承するサブクラスです。
例えば、あるプログラムの処理で、乗り物クラスを継承した任意のサブクラスのオブジェクトが外部から渡されるとします。この時、そのオブジェクトはどのクラスオブジェクトであるかは不明(自動車クラスだか自転車クラスだか飛行機クラスだかは不明)です。その、自動車オブジェクトだか自転車オブジェクトだか飛行機オブジェクトだか何だか分からないけど、とにかくその乗り物を走らせたい、という処理が必要になるとします。このとき、それぞれのサブクラスで、乗り物を走らせるためのメソッドがばらばらに定義されていると、上記の、「なんだかわからないけど走らせたい」という処理は不可能になります。
スーパークラスで戻り値も引数もメソッド名も全て同じ「走る」抽象メソッドを用意することで、実際のプログラムでは、その何だか分からないオブジェクトのメソッドにスーパーで定義された引数を渡せば、以上の要件(何だか分からないオブジェクトを走らせること)が満たされます。
なるほど・・・
「使わないといけない」という風に考えると前よりはずいぶんと分かりました。
これからまだ勉強してオーバーライドのありがたみを感じたいと思います。笑
お答えありがとうございました。
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クラスは変更をうけません。
適当な説明になりましたが、なにかのヒントになれば幸いです。
やっぱりJavaは理解をしていないとなかなか難しいですね・・・
中身を知らなくても動くっていうのはいいとは思います。
どうもありがとうございました。
No.1
- 回答日時:
こんにちは(^ー^)
まず、オーバーライドとオーバーロードは別物です。
オーバーライドは、スーパークラスで定義された実際の処理内容は未定のメソッドをサブクラスで実装(実際の処理内容を記述する)ことです。
オーバーロードは、引数が異なる同じメソッドを複数定義することです。例えば、StringクラスのvalueOfメソッドは、引数の文字列表現を返すメソッドです。ここで、引数には色々な型の値を渡すことが出来ます。例えば、int型の数値を引数に引数に与えれば、その数値の文字列表現を返します。同様に、double型の数値を渡してもその文字列表現、long型の数値を渡してもその文字列表現が返ってきます。これは、実際にはStringクラスに引数の異なる同じvalueOfメソッドが何個も何個も定義されていることにより可能となっています。使っている側にとって、引数にいろいろな型の値を渡せることは大変便利です。これがオーバーロードです。
次に、本題のオーバーライドについてですが、ご質問にあるスーパークラスがabstract修飾子のついた抽象クラスである点を踏まえてお話します。
例えば、乗り物クラスがあったとします。この乗り物クラスを自動車クラス、自転車クラス、オートバイクラス、飛行機クラス等が継承するとします。
まず、スーパークラスである乗り物クラスには、それを継承するどのサブクラスにも共通の、乗り物を動かすための「走る」メソッドが用意されているとします。
しかし、実際に、どうやってその乗り物を走らせるのか、という処理内容については、乗り物クラスを継承する各サブクラスによって異なります。たとえば、自動車クラスでは、エンジンをかけ、アクセルを踏むという処理が必要になります。自転車クラスでは、ペダルに足を乗せ、キコキコペダルを回すという処理が必要になります。つまり、乗り物クラスには、どれも「走る」メソッドが必要なのですが、その処理内容が異なるため、スーパークラスで「走る」メソッドの定義だけ提供し、継承するサブクラスで実際の処理内容を記述するわけです。
だったら、スーパーの乗り物クラスでわざわざ「走る」メソッドなんか定義しなくたって、サブクラスで勝手に定義しちゃえばいいじゃないか、ともいえますが、これはオブジェクト指向に反した考えでしょう。また、ある程度大きなシステムになってくると不都合が生じます。各サブクラスで個別に自由に定義するとすると、例えば、同じ「走る」メソッドについて、自動車クラスを作る人は「運転」メソッドを定義するかもしれません。また、自転車クラスを作る人は、「自転車をこぐ」メソッドを作るかもしれません。こうすると、全体でシステムを眺めたときに、大変管理しずらくなります。そこでまずスーパーの乗り物クラス抽象クラスで定義し、これを継承する全てのサブクラスは必ずクラス内で定義されている「走る」メソッドを実装しなければいけなくします。そして、それを継承するサブクラスで「走る」メソッドについてそれぞれの処理内容を記述すれば、そのシステムについて何も知らない人でも、スーパークラスの「乗り物」クラスを見れば、ああ、これを継承するサブクラスにはみんな必ず「走る」メソッドがあるんだなぁ、と分かりやすくなります。これは1つの側面です。
また、自動車や自転車、飛行機等の乗り物クラスのサブクラスでは、「座席に座る」メソッドを実装しなければいけないとします。この「座席に座る」メソッドは、自動車だろうが、自転車だろうが、飛行機だろうが、どのサブクラスでも処理内容はまったく一緒です(ただ運転する人が座席に座るというだけの処理)。こうした場合、それぞれのサブクラスでいちいち「座席に座る」メソッドを定義するのは愚考でしょう。スーパーの乗り物クラスで、「座席に座る」メソッドを処理内容も含めて定義したほうが得策というか普通です。
話はそれますが、抽象メソッド(処理内容の記述されていないメソッド)を1つでも持つクラスは抽象クラスです。抽象クラスはインスタンス化できません。それを継承するサブクラスで初めてインスタンス化することができます。しかし、抽象クラスを継承するサブクラスが、そのスーパークラスである抽象クラスの持つ抽象メソッドを実装していることが、インスタンス化の条件となります。
上の例ですと、乗り物クラスはそれを継承するどのサブクラスでも共通の「座席に座る」メソッドと、継承するサブクラスによって処理内容の異なる「走る」メソッド(抽象メソッド)が用意されています。これを継承する自動車クラス、自転車クラス等は、「走る」メソッドを実装して初めてインスタンス化することができるようになります。
何度も同じような話で分かりづらくなってしまいましたが、なんとなく見えてきますでしょうか?
私も素人に毛が生えたようなものですので、間違った記載がありましたらすみません。どなたか精通している方の回答を待つことにしましょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP アコーディオンPHPが上手くいかない 3 2022/07/15 16:29
- PHP PHPの構文で間違えが分からない 5 2022/07/11 16:38
- Visual Basic(VBA) エクセルVBAで教えて頂きたいのですが? 2 2022/12/31 20:28
- PHP SQLとPHPの連結方法がわからないのでアドバイスお願い致します 1 2022/07/12 12:16
- Java java final 1 2022/06/10 22:49
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Java Java プログラム public class Main { public static void 3 2023/08/10 23:46
- PHP style.cssのjQuery条件付きcssが機能しない 4 2022/07/17 18:27
- Java 直し方について教えて頂きたいです。 4 2022/08/13 02:11
- 英語 節を列挙する例示表現について 2 2022/08/15 13:52
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Java初級 引数に適用できません
-
C# 点の描き方をおしえてくだ...
-
contextってなんですか?
-
c++のキュー
-
C# 他のnamespaceにあるメソッ...
-
オーバーロード、オーバーライ...
-
Strutsでチェックボックスの値...
-
YYYYMMDD書式の日付に対する適...
-
String.containsの反対機能はあ...
-
レコード件数の表示
-
エクセルVBAで、条件に一致する...
-
3年間同じクラスになる確率
-
インスタンス参照でアクセスで...
-
c++,ある関数のクラスから別の...
-
ワイルドカード<?>と型パラメー...
-
「天声人語」をインターネット...
-
DataGridViewでセルクリックイ...
-
string formatについて
-
クラス間でのデータ参照
-
変数の参照でエラーが出てしま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Java初級 引数に適用できません
-
public static void main (Stri...
-
レコード件数の表示
-
abstract と static を一緒に付...
-
なぜprotected overrideなのか
-
C# 点の描き方をおしえてくだ...
-
コマンドライン引数のチェック
-
String.containsの反対機能はあ...
-
Google Apps Script で getRang...
-
StringBufferからStringへキャ...
-
Java初心者です、エラーの意味...
-
javaに"search"という関数 or ...
-
C# でメソッドに送られてきたOb...
-
YYYYMMDD書式の日付に対する適...
-
メソッド宣言の戻り値の型にク...
-
return new使用時
-
readLine()ではじめから読み直...
-
シェルスクリプトからのJavaメ...
-
Fileの読み取り専用の解除
-
親の親のメソッドを呼ぶには?
おすすめ情報