Javaには継承に関連する機能で、オーバーライドという機能があります。オーバーロードと用語が似ているので混同しないように気を付けましょう。
オーバーライドとは
オーバーライドは継承や実装※を行った際に、サブクラス(実装クラス)側でスーパークラスと同じ名前のメソッドを再定義(上書き)する機能です。
※実装についてはインターフェイスの項目で説明します。
スーパークラスとサブクラスで同じ名前のメソッドが定義することで、サブクラス特有の追加処理を記述することができます。
上の図解では処理Aが処理Bに上書きされます。
(処理Aがオーバーライドされる側、処理Bがオーバーライドする側となります)
オーバーライドのルール
オーバーライドするメソッドはオーバーライドされるメソッドと「戻り値の型」「メソッド名」「引数の型や数」が同じである必要があります。
オーバーライドにはほかにもいくつかルールがありますが、その他のルールは別の記事で紹介します。
例えば以下のようなメソッドを親クラスで定義します。
1 2 3 4 5 |
class SuperClass{ void sort(int[] array){ 配列内のデータを並び替える処理 } } |
次に上のクラスを継承し、メソッドをオーバーライドします。
オーバーライドする側のメソッドでは、配列を並び替えるだけでなく、表示処理も追加されています。
1 2 3 4 5 6 |
class SubClass extends SuperClass{ void sort(int[] array){ 配列内のデータを並び替える処理 並び替えた配列のデータを表示する } } |
しかし、オーバーライドしたつもりでも、以下のようなメソッドを定義した場合はオーバーライドにはなりません。(エラーも起こりません)
1 2 3 4 5 6 |
class SubClass extends SuperClass{ void sort(double[] array){ 配列内のデータを並び替える処理 並び替えた配列のデータを表示する } } |
上のメソッドは親クラスのメソッドとは「引数の型」が異なる為、オーバーロード扱いになります。
オーバーライド サンプルプログラム
以下のプログラムを「Autobike.java」「Number34.java」という名前でworkフォルダ内に保存します。
※すでにAutobike.java、Vehicle.javaを作成済みの場合は、Autobike.javaの追加のメソッド部分を記述してください。Vehicle.javaは継承の記事にあります。
保存が完了したら、コマンドプロンプトを起動し、Number34.javaをコンパイルおよび実行をしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
//乗り物クラスを継承するオートバイクラス(サブクラス) class Autobike extends Vehicle{ private double fuel ; //ガソリンを入れるメソッド void setFuel(double f){ if(f > 0 && f <= 10) fuel = f; } //ガソリン量を表示 void fuelDisplay(){ System.out.println("ガソリンの量は" + fuel + "リットルです。"); } //追加 handleOperation()メソッドのオーバーライド void handleOperation(int c){ if(c >= -45 && c <= 45) handle = c; } //追加 display()メソッドのオーバーライド void display(){ System.out.println("オートバイを運転中。"); } } |
1 2 3 4 5 6 7 8 |
class Number34{ public static void main(String[] args){ Autobike autobike = new Autobike(); autobike.accel(10); //アクセル autobike.handleOperation(50); //ハンドルを切る autobike.display(); //表示 } } |
実行例
C:\work>javac Number34.java
Autobike.java:16: エラー: handleはVehicleでprivateアクセスされます
if(c >= -45 && c <= 45) handle = c;
^
エラー1個
※実行例はコンパイルの例を表示しています。
サンプルプログラムの修正
Autobike.javaはVehicle.javaを継承しており、handleOperation()とdisplay()のオーバーライドを行っています。しかし、handleOperation()メソッド内で利用しているフィールドはprivate宣言されており、継承関係にあってもフィールドを利用することができません。
Vehicle(親)クラスにフィールドにアクセスするためのメソッドを追加する方法もありますが、今回はsuperを利用した記述に変更します。
また、dipslay()内も親クラスのdisplay()の内容を表示できるように変更します。
具体的には以下のようにAutobike.javaを変更します。
※変更の必要がないフィールドやメソッドは割愛しています
保存が完了したら、コマンドプロンプトを起動し、Number34.javaをコンパイルおよび実行をしてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//乗り物クラスを継承するオートバイクラス(サブクラス) class Autobike extends Vehicle{ //変更の必要ないフィールドやメソッドは割愛 //修正 handleOperation()メソッドのオーバーライド void handleOperation(int c){ if(c >= -45 && c <= 45) super.handleOperation(c); } //修正 display()メソッドのオーバーライド void display(){ System.out.println("オートバイを運転中。"); super.display(); } } |
実行例
C:\work>javac Number34.java
C:\work>java Number34
オートバイを運転中。
ただ今直進中です。
スピードは10km/hです。
※実行例はコンパイルおよび実行までの例を表示しています。
オーバーライドとsuper
オーバーライドされたメソッドはサブクラスでも利用ができます。その際はsuperキーワードと併用してメソッドを呼び出します。
スーパークラスのメソッドを利用 | super.メソッド名(引数) ; |
---|---|
記述例 | super.display() ; |
superキーワードを利用することで、スーパークラスのメソッドを利用することを明示し、自クラスのメソッドと区別をつけることで、オーバーライドされる側のメソッドを呼び出すことができます。
しかし、継承関係はスーパークラスとサブクラスで成り立つため、スーパークラスが継承しているクラスのメソッドは利用できません。(以下の図解参照)
オーバーライド 復習問題
- void method(int a, int b)のメソッドをオーバーライドしているメソッドを選んでください。
- オーバーライドの説明として正しいものを選んでください。
- オーバーライドの説明として正しいものを選んでください。
- お疲れ様でした。
-
void method(int x, int y)
void method(int x)
void method(double x, double y)
int method(int a, int b)
-
- 引数で利用する型が異なっていてもオーバーライドできる
- 引数で利用する変数名が異なっていてもオーバーライドできる
- 引数で利用する型の並びが異なっていてもオーバーライドできる
- 戻り値の型が異なっていてもオーバーライドできる
-
- super()でスーパークラスのメソッドにアクセスできる
- override()でスーパークラスのメソッドにアクセスできる
- super.メソッド名()でスーパークラスのメソッドにアクセスできる
- this()でスーパークラスのメソッドにアクセスできる
まとめ
- オーバーライドはサブクラス側でスーパークラスのメソッドを再定義することができる
- オーバーライドはスーパークラスのメソッドと「メソッド名」「戻り値の型」「引数」を同一にする必要がある
- superキーワードを利用することでオーバーライドされる側のメソッドをサブクラス側で利用が可能