Java-overriding

提供:Dev Guides
移動先:案内検索

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

上記の例では、 b はAnimalのタイプですが、Dogクラスのmoveメソッドを実行していることがわかります。 その理由は次のとおりです。コンパイル時に、参照型に対してチェックが行われます。 ただし、ランタイムでは、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にはbarkという名前のメソッドがないため、このプログラムはコンパイル時エラーをスローします。

メソッドのオーバーライドのルール

  • 引数リストは、オーバーライドされたメソッドのリストとまったく同じでなければなりません。
  • 戻り値の型は、スーパークラスの元のオーバーライドされたメソッドで宣言された戻り値の型と同じか、サブタイプでなければなりません。
  • アクセスレベルは、オーバーライドされたメソッドのアクセスレベルよりも制限することはできません。 たとえば、スーパークラスメソッドがパブリックとして宣言されている場合、サブクラスのオーバーライドメソッドはプライベートまたは保護されません。
  • インスタンスメソッドは、サブクラスによって継承される場合にのみオーバーライドできます。
  • finalとして宣言されたメソッドはオーバーライドできません。
  • staticと宣言されたメソッドはオーバーライドできませんが、再宣言できます。
  • メソッドを継承できない場合は、オーバーライドできません。
  • インスタンスのスーパークラスと同じパッケージ内のサブクラスは、privateまたはfinalとして宣言されていないスーパークラスメソッドをオーバーライドできます。
  • 別のパッケージのサブクラスは、publicまたはprotectedとして宣言された非最終メソッドのみをオーバーライドできます。
  • オーバーライドされたメソッドは、オーバーライドされたメソッドが例外をスローするかどうかに関係なく、チェック解除例外をスローできます。 ただし、オーバーライドするメソッドは、オーバーライドされたメソッドによって宣言されたものよりも新しい、または広範なチェック済み例外をスローしないでください。 オーバーライドするメソッドは、オーバーライドするメソッドよりも狭い、または少ない例外をスローできます。
  • コンストラクターはオーバーライドできません。

superキーワードの使用

オーバーライドされたメソッドのスーパークラスバージョンを呼び出す場合、 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