メソッドのオーバーライド
クラスを継承してサブクラスを定義した場合、サブクラスではスーパークラスで定義されているメソッドと同じ名前、同じ引数を持つメソッドを定義することができます。これをメソッドのオーバーライドと呼びます。オーバーライドを利用すると、スーパークラスで定義されているメソッドをサブクラスで上書きし、異なる処理を実装することができます。ここではオブジェクト指向におけるメソッドのオーバーライドの使い方について解説します。
メソッドのオーバーライドとは
クラスを継承した場合、サブクラスはスーパークラスのフィールドやメソッドを引き継いで利用することができます。ただし、スーパークラスで定義されているメソッドの処理内容をサブクラス側で変更したい場合もあります。
このとき、スーパークラスで定義されているメソッドと同じ名前で、同じ引数を持つメソッドをサブクラスで定義することで、メソッドの処理内容を上書きすることができます。この仕組みをメソッドのオーバーライドといいます。
メソッドのオーバーライドを利用することで、スーパークラスの基本的な仕組みを利用しながら、サブクラスごとに異なる処理を実装することができます。
簡単な例で確認してみます。次の例では、スーパークラス Product に showName メソッドが定義されています。そして Product クラスを継承した Foods クラスと Gadgets クラスを定義します。
class Product {
public void showName() {
System.out.println("製品の名前を表示します");
}
}
class Foods extends Product {
}
class Gadgets extends Product {
}
サブクラスのオブジェクトはスーパークラスのメソッドを利用できるので、次のようにサブクラスのオブジェクトから呼び出すことができます。
public class Sample {
public static void main(String[] args) {
Foods f = new Foods();
f.showName();
Gadgets g = new Gadgets();
g.showName();
}
}
実行結果は次のようになります。
製品の名前を表示します 製品の名前を表示します
Foods クラスについては showName メソッドを呼び出したときに異なる処理をしたい場合、同じ名前と引数を持つメソッドを Foods クラスに定義することができます。
class Product {
public void showName() {
System.out.println("製品の名前を表示します");
}
}
class Foods extends Product {
public void showName() {
System.out.println("食料品の名前を表示します");
}
}
class Gadgets extends Product {
}
この場合 Gadgets クラスのオブジェクトから showName メソッドを呼び出した場合は、スーパークラスの showName メソッドが呼び出されますが、 Foods クラスのオブジェクトから showName メソッドを呼び出した場合は Foods クラスで定義されている showName メソッドが呼び出されます。
public class Sample {
public static void main(String[] args) {
Foods f = new Foods();
f.showName();
Gadgets g = new Gadgets();
g.showName();
}
}
実行結果は次のようになります。
食料品の名前を表示します 製品の名前を表示します
このようにサブクラスで共通して使用されるメソッドについてはスーパークラスで定義しつつ、特定のサブクラスだけ異なる処理をさせたい場合は、メソッドのオーバーライドを利用します。
superを使ってスーパークラスのメソッドを呼び出す
サブクラスでスーパークラスのメソッドをオーバーライドした場合でも、必要に応じてスーパークラスのメソッドを呼び出すことができます。このときに使用するのが super キーワードです。
class Product {
void showName() {
System.out.println("製品の名前を表示します");
}
}
class Foods extends Product {
void showName() {
super.showName();
System.out.println("食料品の名前を表示します");
}
}
この場合 Foods クラスのオブジェクトから showName メソッドを呼び出した場合、まずスーパークラスの showName メソッドが呼び出され、そのあとで残りの処理が実行されます。
public class Sample {
public static void main(String[] args) {
Foods f = new Foods();
f.showName();
}
}
実行結果は次のようになります。
製品の名前を表示します 食料品の名前を表示します
※ super キーワードは別の用途でも使用されます。詳しくは「superキーワード」を参照されてください。
オーバーライドするときの注意点
メソッドをオーバーライドする場合、スーパークラスと同じメソッド名、同じ引数を持つメソッドを定義する必要があります。
メソッド名:同じ 引数の数:同じ 引数のデータ型:同じ
引数の数や型が異なっている場合、それはオーバーライドではなくメソッドのオーバーロードとなりますので注意してください。
メソッドの戻り値については、同じデータ型であるか、またはスーパークラスのメソッドの戻り値のデータ型のサブクラスである必要があります。
例えばスーパークラスのメソッドの戻り値が Object 型の場合に、オーバーライドしたメソッドの戻り値が String 型でも問題ありません。ただしスーパークラスのメソッドの戻り値が String 型の場合、オーバーライドしたメソッドの戻り値を int 型にすることはできません。
またアクセス修飾子として private が付いたスーパークラスのメソッドは、サブクラスからアクセスできないためオーバーライドすることはできません。
@Overrideアノテーションとは
メソッドをオーバーライドするときには、メソッドの前に @Override を付けることがあります。これはアノテーションと呼ばれるもので、このメソッドがスーパークラスのメソッドをオーバーライドしていることをコンパイラに伝えるためのものです。
@Override を付けなくてもメソッドのオーバーライドは行えますが、付けておくことでプログラムのミスを防ぐことができます。その為、メソッドをオーバーライドするときには @Override を付けておくのが一般的です。
次の例では Product クラスの showName メソッドを Foods クラスでオーバーライドしています。
class Product {
public void showName() {
System.out.println("製品の名前を表示します");
}
}
class Foods extends Product {
@Override
public void showName() {
System.out.println("食料品の名前を表示します");
}
}
@Override を付けることで、このメソッドがスーパークラスのメソッドをオーバーライドしていることが明示されます。
@Override を付けておくと、もしオーバーライドの条件を満たしていない場合にコンパイルエラーとして検出することができます。次の例を見てください。
class Product {
public void showName() {
System.out.println("製品の名前を表示します");
}
}
class Foods extends Product {
@Override
public void showname() {
System.out.println("食料品の名前を表示します");
}
}
この例では showName ではなく showname と書いてしまっています。結果としてオーバーライドしているつもりで、別のメソッドを定義していることになります。 @Override が付いている場合、このメソッドはオーバーライドになっていないためコンパイルエラーとなり、プログラムのミスを発見しやすくなります。
-- --
オブジェクト指向におけるメソッドのオーバーライドの使い方について解説しました。
( Written by Tatsuo Ikura )
著者 / TATSUO IKURA
これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。