やあ!あなたはすでに Java メソッドを使用しており、それについてよく知っています。おそらく、1 つのクラスに同じ名前でパラメーターが異なるメソッドが多数あるという状況に直面したことがあるでしょう。このような場合にメソッドのオーバーロードを使用したことを思い出してください。今日は別の状況を検討します。単一の共有メソッドがあるが、異なるクラスで異なる処理を実行する必要があると想像してください。この動作をどのように実装すればよいでしょうか? 理解するために、動物を表すAnimal親クラスを考えてみましょう。その中に speechメソッドを作成します。
public class Animal {
public void speak() {
System.out.println("Hello!");
}
}
まだプログラムを書き始めたばかりですが、おそらく潜在的な問題があることに気づいたでしょう。世界にはたくさんの動物がいますが、猫はニャーと鳴き、アヒルは鳴き声を上げ、ヘビはシューシューと鳴くなど、それぞれが異なる「話し方」をします。 私たちの目標はシンプルです。大量の話し方を作成しないようにすることです。ニャー鳴くためのcatSpeak()メソッドやシューという鳴き声のためのSnakeSpeak()メソッドなどを作成する代わりに、 speak()を呼び出します。ヘビのシューシュー音、猫の鳴き声、犬の鳴き声を鳴らします。メソッドのオーバーライドを使用すると、これを簡単に実現できます。Wikipedia には、「オーバーライド」という用語について次の説明があります。 オブジェクト指向プログラミングにおけるメソッド オーバーライドは、サブクラスまたは子クラスが、そのスーパークラスまたはそのスーパークラスの 1 つによってすでに提供されているメソッドの特定の実装を提供できるようにする言語機能です。親クラス それは本質的に正しいです。メソッドのオーバーライドを使用すると、親クラスのメソッドを取得して、各子クラスに独自の実装を作成できます。新しい実装は、子クラスの親の実装を「置き換え」ます。これがどのようになるかを例で見てみましょう。Animalクラスを継承する 4 つのクラスを作成します。
public class Bear extends Animal {
@Override
public void speak() {
System.out.println("Growl!");
}
}
public class Cat extends Animal {
@Override
public void speak() {
System.out.println("Meow!");
}
}
public class Dog extends Animal {
@Override
public void speak() {
System.out.println("Woof!");
}
}
public class Snake extends Animal {
@Override
public void speak() {
System.out.println("Hiss!");
}
}
「将来のための小さなライフハックです。親クラスのメソッドをオーバーライドするには、IntelliJ IDE で子クラスのコードに移動し、Ctrl+O をクリックして、メニューの [メソッドをオーバーライド...] を選択します。ホット キーの使用に慣れてください。最初から — プログラムをより速く書くのに役立ちます! 必要な動作を指定するために、いくつかのことを行いました。
- 各子クラスで、親クラスのメソッドと同じ名前のメソッドを作成しました。
- 私たちはコンパイラーに、メソッドに親クラスと同じ名前を付けるのは偶然ではなく、その動作をオーバーライドしたいと伝えました。これをコンパイラに伝えるために、メソッドの上に @Override アノテーションを設定します。
@Override アノテーションをメソッドの上に配置すると、コンパイラ (およびコードを読むプログラマ) に「すべて問題ありません」と通知されます。これは間違いではありません。忘れっぽいわけではないんです。このようなメソッドが既に存在することは承知しており、それをオーバーライドしたいと考えています。」 - 各子クラスに必要な実装を作成しました。speech()メソッドが呼び出されると、ヘビはシューシューという音を立て、クマはうなり声を上げます。
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
Animal animal3 = new Bear();
Animal animal4 = new Snake();
animal1.speak();
animal2.speak();
animal3.speak();
animal4.speak();
}
}
コンソール出力:
Woof!
Meow!
Growl!
Hiss!
素晴らしい!すべてが正常に機能します。Animal親クラスのオブジェクトを格納する 4 つの参照変数を作成し、4 つの異なる子クラスのインスタンスをそれらに割り当てました。その結果、各オブジェクトは独自の動作を示します。各子クラスでは、オーバーライドされたspeech()メソッドが、 Animalクラスの「ネイティブ」speak()メソッド(単に「Hello!」を表示する) を置き換えました。 オーバーライドにはいくつかの制限があります。
-
オーバーライドされたメソッドには、親メソッドと同じパラメータが必要です。
親クラスのspeakメソッドにStringパラメータがある場合、子クラスのオーバーライドされたメソッドにもStringパラメータが必要です。それ以外の場合、コンパイラはエラーを生成します。
public class Animal { public void speak(String s) { System.out.println("Hello! " + s); } } public class Cat extends Animal { @Override // Error! public void speak() { System.out.println("Meow!"); } }
-
オーバーライドされたメソッドの戻り値の型は、親メソッドと同じである必要があります。
そうしないと、コンパイラ エラーが発生します。
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override public String speak() { // Error! System.out.println("Meow!"); return "Meow!"; } }
-
オーバーライドされたメソッドのアクセス修飾子も、「元の」メソッドと同じである必要があります。
public class Animal { public void speak() { System.out.println("Hello!"); } } public class Cat extends Animal { @Override private void speak() { // Error! System.out.println("Meow!"); } }