Java-オーバーライド
前の章では、スーパークラスとサブクラスについて説明しました。クラスがそのスーパークラスからメソッドを継承する場合、finalとマークされていない限り、メソッドをオーバーライドする可能性があります。
オーバーライドの利点は次のとおりです。サブクラスタイプに固有の動作を定義する機能。つまり、サブクラスはその要件に基づいて親クラスメソッドを実装できます。
オブジェクト指向の用語では、オーバーライドとは、既存のメソッドの機能をオーバーライドすることを意味します。
例
例を見てみましょう。
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
}
}
これにより、次の結果が生成されます-
出力
Animals can move
Dogs can walk and run
上記の例では、 bDogクラスのmoveメソッドを実行するAnimalの一種です。この理由は次のとおりです。コンパイル時に、参照型がチェックされます。ただし、実行時に、JVMはオブジェクトタイプを把握し、その特定のオブジェクトに属するメソッドを実行します。
したがって、上記の例では、Animalクラスにメソッドmoveがあるため、プログラムは正しくコンパイルされます。次に、実行時に、そのオブジェクトに固有のメソッドを実行します。
次の例を考えてみましょう-
例
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
System.out.println("Dogs can walk and run");
}
public void bark() {
System.out.println("Dogs can bark");
}
}
public class TestDog {
public static void main(String args[]) {
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
a.move(); // runs the method in Animal class
b.move(); // runs the method in Dog class
b.bark();
}
}
これにより、次の結果が生成されます-
出力
TestDog.java:26: error: cannot find symbol
b.bark();
^
symbol: method bark()
location: variable b of type Animal
1 error
bの参照型Animalには樹皮という名前のメソッドがないため、このプログラムはコンパイル時エラーをスローします。
メソッドのオーバーライドのルール
引数リストは、オーバーライドされたメソッドの引数リストとまったく同じである必要があります。
戻り値の型は、スーパークラスの元のオーバーライドされたメソッドで宣言された戻り値の型と同じか、サブタイプである必要があります。
アクセスレベルは、オーバーライドされたメソッドのアクセスレベルよりも制限することはできません。例:スーパークラスメソッドがパブリックとして宣言されている場合、サブクラスのオーバーライドメソッドをプライベートにすることも保護することもできません。
インスタンスメソッドは、サブクラスに継承されている場合にのみオーバーライドできます。
finalと宣言されたメソッドはオーバーライドできません。
staticと宣言されたメソッドはオーバーライドできませんが、再宣言できます。
メソッドを継承できない場合は、オーバーライドできません。
インスタンスのスーパークラスと同じパッケージ内のサブクラスは、privateまたはfinalとして宣言されていないスーパークラスメソッドをオーバーライドできます。
別のパッケージのサブクラスは、publicまたはprotectedと宣言された非finalメソッドのみをオーバーライドできます。
オーバーライドされたメソッドが例外をスローするかどうかに関係なく、オーバーライドするメソッドはチェック解除された例外をスローできます。ただし、オーバーライドするメソッドは、オーバーライドされたメソッドによって宣言されたものよりも新しい、またはより広いチェック済み例外をスローしないようにする必要があります。オーバーライドするメソッドは、オーバーライドされるメソッドよりも狭い、または少ない例外をスローできます。
コンストラクターはオーバーライドできません。
スーパーキーワードの使用
オーバーライドされたメソッドのスーパークラスバージョンを呼び出す場合、 super キーワードが使用されます。
例
class Animal {
public void move() {
System.out.println("Animals can move");
}
}
class Dog extends Animal {
public void move() {
super.move(); // invokes the super class method
System.out.println("Dogs can walk and run");
}
}
public class TestDog {
public static void main(String args[]) {
Animal b = new Dog(); // Animal reference but Dog object
b.move(); // runs the method in Dog class
}
}
これにより、次の結果が生成されます-
出力
Animals can move
Dogs can walk and run