手を動かして学ぶ Java入門 (メソッドのオーバーライド)
環境構築不要! ブラウザから直接コードを実行できます。
本記事では、クラス・メソッドのオーバーライドについて学びます。
オブジェクト指向の大事な概念である ポリモーフィズム(多態性) の基本でもあります。
15分くらいで、さくっと終わる記事をめざしています。
シリーズ一覧
- シリーズ
- 手を動かして学ぶ Java入門 (Hello world 編)
- 手を動かして学ぶ Java入門 (数値と演算)
- 手を動かして学ぶ Java入門 (数値と変数)
- 手を動かして学ぶ Java入門 (コメントの書き方)
- 手を動かして学ぶ Java入門 (文と式の違い)
- 手を動かして学ぶ Java入門 (if文)
- 手を動かして学ぶ Java入門 (if-else文、if-elseif文)
- 手を動かして学ぶ Java入門 (文字列の連結)
- 手を動かして学ぶ Java入門 (while文)
- 手を動かして学ぶ Java入門 (break文)
- 手を動かして学ぶ Java入門 (continue文)
- 手を動かして学ぶ Java入門 (for文)
- 手を動かして学ぶ Java入門 (クラスの超基本)
- 手を動かして学ぶ Java入門 (クラス・メソッド)
- 手を動かして学ぶ Java入門 (クラス・フィールド)
- 手を動かして学ぶ Java入門 (クラス・コンストラクタ)
- 手を動かして学ぶ Java入門 (文字列クラス)
- 手を動かして学ぶ Java入門 (静的メソッド)
- 手を動かして学ぶ Java入門 (静的フィールド)
- 手を動かして学ぶ Java入門 (定数の定義)
- 手を動かして学ぶ Java入門 (クラス継承の超基本)
- 手を動かして学ぶ Java入門 (メソッドのオーバーライド)
- 手を動かして学ぶ Java入門 (メソッドのオーバーロード)
続きは近日公開予定!
はじめに
この記事は paiza.IO の「Online Java compiler」を利用しています。
2024/12/17 現在、上記環境の Java バージョンは 18 です。(paiza.IO利用ガイド)
実行したコードは paiza.IO で保存および公開されることがあります。
そのため、個人情報などの機密性の高い情報は、コードとして入力しないようにご注意ください。
詳細は paiza.IO の利用規約およびプライバシーポリシーをご確認ください。
クラス継承のおさらい
クラスの継承とは、簡単にいうと…
- ベースとなるクラスの フィールド と メソッド
- それを 引き継いだ 新しいクラスを作る (宣言する)
ことです。
メソッドのオーバーライド
オーバーライド (override) とは、本来は「優先する」や「覆す」などといった意味があります。
プログラミングにおいては「上書き」と意訳するとしっくりきます。
メソッドのオーバーライドとは、簡単にいうと…
- スーパークラスで宣言したメソッドを、
- サブクラスで同じメソッドとして宣言して 上書き する
ことです。
具体的な例で見てみましょう。
Shape は「図形」という意味のクラスです。
public class Shape {
public void print() {
System.out.println("図形の名前 : なし");
}
}
print メソッドは、図形の名前を出力します。
Shape クラスは「具体的な図形」ではないので、名前は "なし" としています。
次に、Shape クラスを継承した Rectangle クラスを作りましょう。
Rectangle は「長方形」という意味です。
public class Rectangle extends Shape {
}
Rectangle クラスの中身は空です。
(まだメソッドのオーバーライドはしていません)
それでは、この2つのクラスを実際に動かして確認してみましょう。
Shape shape = new Shape();
shape.print();
Rectangle rectangle = new Rectangle();
rectangle.print();
Shape クラスと Rectangle クラスのインスタンスを作成して、それぞれ print メソッドを呼び出してみます。
結果がどうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか? 「出力」のところに
図形の名前 : なし
図形の名前 : なし
と表示されたら成功です。
ここまでは前回までの復習ですね。
次は、Rectangle クラスにメソッドを1つ宣言してみましょう。
宣言するのは、Shape クラスと同じ名前の print メソッドです。
public class Rectangle extends Shape {
@Override
public void print() {
System.out.println("図形の名前 : 長方形");
}
}
( @Override という見慣れない記述もありますが、そちらは今は気にしないでください)
それでは実際に動かして確認してみましょう。
結果がどうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか? 「出力」のところに
図形の名前 : なし
図形の名前 : 長方形
と表示されたら成功です。
コードの解説
最初に「オーバーライドしない例」を見てみましょう。
public class Shape {
public void print() {
System.out.println("図形の名前 : なし");
}
}
public class Rectangle extends Shape {
}
この場合は、Rectangle のインスタンスの print メソッドを呼び出すと…
Rectangle rectangle = new Rectangle();
rectangle.print();
^^^^^^^ <--- Shape の print メソッドが呼び出される
Shape の print メソッドが呼び出されます。
結果の出力↓
図形の名前 : なし
次は「オーバーライドする例」です。
public class Shape {
... 省略 ...
}
public class Rectangle extends Shape {
@Override
public void print() {
System.out.println("図形の名前 : 長方形");
}
}
この場合は、Rectangle のインスタンスの print メソッドを呼び出すと…
Rectangle rectangle = new Rectangle();
rectangle.print();
^^^^^^^ <--- Rectangle の print メソッドが呼び出される
オーバーライドされた Rectangle の print メソッドが呼び出されます。
結果の出力↓
図形の名前 : 長方形
ここが大事なポイントです。
Rectangle クラスは Shape クラスを継承しています。
そのため、通常であれば Shape クラスの print メソッドを 引き継ぎ ます。
しかし、Rectangle クラスで print メソッドを オーバーライド することで、Shape クラスの print メソッドを上書きしたわけですね。
アノテーション
メソッドをオーバーライドするときに記述する、アットマーク(@) を使った書き方を アノテーション といいます。
public class Rectangle extends Shape {
@Override <--- ★この部分!
public void print() {
...
}
}
メソッドをオーバーライドするときは必ず @Override を書くようにしましょう。
書かなくてもエラーにはなりませんが、おすすめはしません。
【 @Override を書くことによるメリット 】
- オーバーライドしたメソッドであることが 明確 になります。
- メソッド名を間違えたりしてオーバーライドできないときは、コンパイルエラーで知らせてくれます。
暗黙の型変換
Java では、サブクラスのインスタンスをスーパークラス型の変数に代入できます。
これを 暗黙の型変換 といいます。
public class Shape {
public void print() {
System.out.println("図形の名前 : なし");
}
}
public class Rectangle extends Shape {
@Override
public void print() {
System.out.println("図形の名前 : 長方形");
}
}
Shape shape = new Rectangle();
^^^^^ ^^^^^^^^^ <--- サブクラス
<--- スーパークラス
こんな感じですね。
さて、shape 変数は Shape 型です。
その変数で print メソッドを呼び出すと、どうなるでしょうか…?
Shape shape = new Rectangle();
shape.print();
Shape クラスで宣言した print メソッドが呼び出される?
それとも、Rectangle クラスでオーバーライドした print メソッドが呼び出される?
実際に動かして確認してみましょう。
結果がどうなるか予想してから「実行(Ctrl-Enter)」ボタンを押してください。
注意:コードは3ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
いかがでしたでしょうか? 「出力」のところに
図形の名前 : 長方形
と表示されたら成功です。
正解は、
- Rectangle クラスでオーバーライドした print メソッドが呼び出される
でした。
これこそが ポリモーフィズム(多態性) の基本になります。
ノート
- 暗黙ではなく、明示的 な型変換もあります。
ただし、あまり使うことはないので、この記事では割愛します。(いずれ解説できたらなと…)
ポリモーフィズム(多態性)
Java は オブジェクト指向プログラミング 言語です。
そして、ポリモーフィズム(多態性)はオブジェクト指向の大事な概念の1つです。
ただ、オブジェクト指向にまつわるお話は難しいので、入門記事としては解説は割愛します。
Java に慣れてきたら、ぜひオブジェクト指向についても学んでみてくださいね。
応用問題
【問題】
まずは、下記のプログラムをそのまま「実行(Ctrl-Enter)」してみましょう。
結果として次のように「出力」に表示されたはずです。
図形の名前 : なし
図形の名前 : なし
図形の名前 : なし
そこで問題です。
Shape クラスを継承した、
- Rectangle クラス
- Circle クラス
に対して、Shape クラスの getName メソッドをオーバーライドしてください。
その結果として、プログラムを実行すると、
図形の名前 : なし
図形の名前 : 長方形
図形の名前 : 円形
と「出力」に表示されようにしてください。
それでは、Rectangle クラスと Circle クラスを修正してから「実行(Ctrl-Enter)」してみましょう。
(修正するのは Rectangle クラスと Circle クラスだけです)
注意:コードは4ファイルあります。上部のタブで切り替え可能です。
(表示がおかしいときは「コードの再読み込み」ボタンを押してみてください)
無事に、
図形の名前 : なし
図形の名前 : 長方形
図形の名前 : 円形
と出力されましたでしょうか?
もし解けなかった場合は、下記の回答例をご参照ください。
回答例
【コード】
public class Rectangle extends Shape {
// getName メソッドをオーバーライドしてください。
@Override
public String getName() {
return "長方形";
}
}
public class Circle extends Shape {
// getName メソッドをオーバーライドしてください。
@Override
public String getName() {
return "円形";
}
}
※ Main.java, Shape.java は書き換えません。
【出力】
図形の名前 : なし
図形の名前 : 長方形
図形の名前 : 円形
まとめ
メソッドのオーバーライドとは、
- スーパークラスで宣言したメソッドを、
- サブクラスで同じメソッドとして宣言して 上書き する
ことです。
オブジェクト指向の大事な概念である ポリモーフィズム(多態性) の基本でもあります。
ぜひ有効に活用していきたいですね。
次回は「手を動かして学ぶ Java入門 (メソッドのオーバーロード)」になります。
関連記事
- シリーズ
- 手を動かして学ぶ Java入門 (Hello world 編)
- 手を動かして学ぶ Java入門 (数値と演算)
- 手を動かして学ぶ Java入門 (数値と変数)
- 手を動かして学ぶ Java入門 (コメントの書き方)
- 手を動かして学ぶ Java入門 (文と式の違い)
- 手を動かして学ぶ Java入門 (if文)
- 手を動かして学ぶ Java入門 (if-else文、if-elseif文)
- 手を動かして学ぶ Java入門 (文字列の連結)
- 手を動かして学ぶ Java入門 (while文)
- 手を動かして学ぶ Java入門 (break文)
- 手を動かして学ぶ Java入門 (continue文)
- 手を動かして学ぶ Java入門 (for文)
- 手を動かして学ぶ Java入門 (クラスの超基本)
- 手を動かして学ぶ Java入門 (クラス・メソッド)
- 手を動かして学ぶ Java入門 (クラス・フィールド)
- 手を動かして学ぶ Java入門 (クラス・コンストラクタ)
- 手を動かして学ぶ Java入門 (文字列クラス)
- 手を動かして学ぶ Java入門 (静的メソッド)
- 手を動かして学ぶ Java入門 (静的フィールド)
- 手を動かして学ぶ Java入門 (定数の定義)
- 手を動かして学ぶ Java入門 (クラス継承の超基本)
- 手を動かして学ぶ Java入門 (メソッドのオーバーライド)
- 手を動かして学ぶ Java入門 (メソッドのオーバーロード)