■オーバーライドの基本的用法
「オーバーライド」は「オーバーロード」のように同じメソッド名を使います
オーバーライド=再定義の言葉通り継承した親クラスにあるメソッドの処理内容をまったく別のものに書き換えたり処理の前後に処理を追加したりするときに利用する
■サンプルプログラム
今回取り扱うヤツはソースコードを見ないとピンと来ないはずなので、
public class SuperProg {
String name;
public SuperProg(String name) {this.name = name; }
public void show() {System.out.println("親は" + name) ; }
}
public class SubProg extends SuperProg {
public SubProg(String name) {super(name);}
public void show() { System.out.println("オーバーライドしたので新しい親は" + name) ; }
}
public class SubProg2 extends SuperProg{
public SubProg2(name) { super(name) ; }
public void show(String name) {
super.show();
System.out.println("オーバーライドしたけど親の処理は完了した!") ;
System.out.println("それを実現した子は" +name2);
}
}
public class MainProg{
public static void main(String [] age) {
SuperProg sp = new SuperProg("田中");
SubProg sb = new SubProg("鈴木");
SubProg2 sb2 = new SubProg2("田中");
sp.show(); //1
sb.show(); //2
sb2.show("伊藤"); //3
}
}
String name;
public SuperProg(String name) {this.name = name; }
public void show() {System.out.println("親は" + name) ; }
}
public class SubProg extends SuperProg {
public SubProg(String name) {super(name);}
public void show() { System.out.println("オーバーライドしたので新しい親は" + name) ; }
}
public class SubProg2 extends SuperProg{
public SubProg2(name) { super(name) ; }
public void show(String name) {
super.show();
System.out.println("オーバーライドしたけど親の処理は完了した!") ;
System.out.println("それを実現した子は" +name2);
}
}
public class MainProg{
public static void main(String [] age) {
SuperProg sp = new SuperProg("田中");
SubProg sb = new SubProg("鈴木");
SubProg2 sb2 = new SubProg2("田中");
sp.show(); //1
sb.show(); //2
sb2.show("伊藤"); //3
}
}
--------------
†実行結果†
--------------
親は田中
オーバーライドしたので新しい親は鈴木
親は田中
オーバーライドしたけど親の処理は完了した!
それ実現した子は伊藤
---------------
それぞれのクラスの出力を注釈で1,2,3と区別してみました
1はスーパークラスのメソッドで実行結果の1行目です
2はサブクラスでオーバーライドしているので同じメソッドを呼び出しても中身が違うのでまったく違う処理なので実行結果の2行目です
3はオーバーライドをするけどもスーパークラスの処理は残しておきたいというメソッドで実行結果ではまずスーパークラスの処理をするため3行目が1行目と同じになる。そして4行目と5行目はオーバーライドしたサブクラスの処理です
こんなかんじでメソッドを1からカスタマイズしたり拡張させる感じで追加カスタマイズをスーパークラスにするのがオーバーライドです
注意する点はオーバーライドするメソッドはfinal修飾子がないことぐらいです。
■オブジェクト変数の暗黙的型変換
double ten;
ten = 1.5;
ten+= 10;
ten*=2;
System.out.println(ten);
のように数値型の場合int数値を「double」や「long」に入れてもなにエラーにならず上記の実行結果で「ten」は「23.0」と出力される
int →long→double→Stringといった感じで変数の大きさが決まっており右へ行くほど大きいため矢印の向きを間違えなければ型変換の記述をしなくても動作してくれる(向きを間違えると必ずコンパイルエラー)
継承関係が成立するクラスの間でも似たようなことができる
それぞれのクラスの出力を注釈で1,2,3と区別してみました
1はスーパークラスのメソッドで実行結果の1行目です
2はサブクラスでオーバーライドしているので同じメソッドを呼び出しても中身が違うのでまったく違う処理なので実行結果の2行目です
3はオーバーライドをするけどもスーパークラスの処理は残しておきたいというメソッドで実行結果ではまずスーパークラスの処理をするため3行目が1行目と同じになる。そして4行目と5行目はオーバーライドしたサブクラスの処理です
こんなかんじでメソッドを1からカスタマイズしたり拡張させる感じで追加カスタマイズをスーパークラスにするのがオーバーライドです
注意する点はオーバーライドするメソッドはfinal修飾子がないことぐらいです。
■オブジェクト変数の暗黙的型変換
double ten;
ten = 1.5;
ten+= 10;
ten*=2;
System.out.println(ten);
のように数値型の場合int数値を「double」や「long」に入れてもなにエラーにならず上記の実行結果で「ten」は「23.0」と出力される
int →long→double→Stringといった感じで変数の大きさが決まっており右へ行くほど大きいため矢印の向きを間違えなければ型変換の記述をしなくても動作してくれる(向きを間違えると必ずコンパイルエラー)
継承関係が成立するクラスの間でも似たようなことができる
Class | スーパークラスのコンストラクタ | サブクラスのコンストラクター |
---|---|---|
スーパークラス | ○ | ○ |
サブクラス | × | ○ |
考えてみれば当然のこですね
■ポリモリフィズム
上記の表からスーパークラスはサブクラスのコンストラクターを使っても生成可能
ポリモリフィズムはいろいろなところで
「同じ呼び出しで異なる振る舞いをする」
と説明されてるがこれをJava風に言い直すと「スーパークラスをサブクラスのコンストラクタで生成し、サブクラスがオーバーライドしたメソッドを実行する」
この場合サブクラスは複数存在している
あまり言葉じゃ説明できなさそうなので、オーバーライドのときに使った3つクラスを使って解説します
public class MainCall{
public static void main(String [] age) {
SuperProg sp1 = new SubProg("山田"); //SubProgのふるまい
SuperProg sp2 = new SubProg2("渡辺"); //SubProg2のふるまい
System.out.println(1);
sp1.show();
System.out.printlen(2);
sp2.show("伊藤");
}
}
--------------public static void main(String [] age) {
SuperProg sp1 = new SubProg("山田"); //SubProgのふるまい
SuperProg sp2 = new SubProg2("渡辺"); //SubProg2のふるまい
System.out.println(1);
sp1.show();
System.out.printlen(2);
sp2.show("伊藤");
}
}
†実行結果†
--------------
1
オーバーライドしたので新しい親は山田
2
親は渡辺
親は渡辺
オーバーライドしたけど親の処理は完了した!
それ実現した子は伊藤
---------------
つまりshow()の出力がどちらも同じSuperProgのオブジェクトなのにサブクラスとして振舞っていることになる
これでどちらもSuperクラスのshow()メソッドを呼び出しているが振る舞いがことなる状況となった
これこそポリモルフィズムである
しかしこれができるのはあくまでオーバーライドしたメソッドのみであって継承後に追加したメソッドを呼び出すとエラーになる
つまりshow()の出力がどちらも同じSuperProgのオブジェクトなのにサブクラスとして振舞っていることになる
これでどちらもSuperクラスのshow()メソッドを呼び出しているが振る舞いがことなる状況となった
これこそポリモルフィズムである
しかしこれができるのはあくまでオーバーライドしたメソッドのみであって継承後に追加したメソッドを呼び出すとエラーになる