継承(extends)

継承はオブジェクト指向言語の主要概念の1つで、とあるクラス(親クラス)の特性やメソッドを別クラス(子クラス)に引き継ぐことです。

継承のサンプル

親クラスを継承した子クラスを定義するには、extendsキーワードを使用します。


// 親クラス
class Animal {
  void voice() {
    System.out.println("うー");
  }

  voice sleep(){
    System.out.println("ぐーぐー");
  }
}

// 子クラス
class Cat extends Animal {
  @Override
  void voice() {
    System.out.println("にゃー");
  }
}

上の例ではAnimalクラスを継承してCatクラスを定義しています。 Catクラスではsleepメソッドは定義していませんが、Animalクラス(親クラス)にsleepメソッドが定義されているため、特性が引き継がれてCatクラスでもsleepメソッドを使用できます。

voiceメソッドはAnimalクラスにもCatクラスにも定義してありますが、こういう場合はメソッドを上書きしたという意味になり、Catクラスのvoiceメソッドが有効になります。 この仕組みのことをオーバーライドと呼びます。

また、Java言語では複数の親を同時に継承すること(多重継承)はできません。1つの親クラスのみを継承する単一継承のみが可能です。

継承時の呼ばれ方

継承時のコンストラクタとメソッドの呼ばれ方をサンプルソースでまとめてみました。

親クラスでは、コンストラクタ(引数あり、なし)、メソッド1、メソッド2を定義します。

(SuperClass.java)

public class SuperClass {

  //コンストラクタ(引数なし)
  public SuperClass(){
    System.out.println("Super-con");
  }

  //コンストラクタ(引数あり)
  public SuperClass(String str){
    System.out.println("Super-con2");
  }

  //メソッド1
  public void m1(){
    System.out.println("super-m1");
  }

  //メソッド2
  public void m2(){
    System.out.println("super-m2");
  }
}

子クラスでは、コンストラクタ(引数あり、なし)とメソッド2をオーバーライドします。

(SubClass.java)

public class SubClass extends SuperClass {

  //コンストラクタ(引数なし)
  public SubClass(){
    System.out.println("SubClass-con");
  }

  //コンストラクタ(引数あり)
  public SubClass(String str){
    System.out.println("SubClass-con2");
  }

  //メソッド2をオーバーライド
  public void m2(){
    System.out.println("sub-m2");
  }
}

実行クラスで子クラスを実行してみましょう。

(ExtendsTest.java)

public class ExtendsTest {

  public static void main(String[] args) {

    //子クラスをインスタンス化(引数なし)
    SubClass sc1 = new SubClass();
    sc1.m1();    //親クラスメソッドを呼出
    sc1.m2();    //オーバーライドメソッドを呼出

    System.out.println();

    //子クラスをインスタンス化(引数あり)
    SubClass sc2 = new SubClass("hoge");
    sc2.m1();    //親クラスメソッドを呼出
    sc2.m2();    //オーバーライドメソッドを呼出
  }
}
(実行結果)
C:\>java ExtendsTest Super-con SubClass-con super-m1 sub-m2 Super-con SubClass-con2 super-m1 sub-m2

以上の結果から継承時の処理の呼ばれ方は以下のようになります。

  • 親クラスのコンストラクタは子クラスのコンストラクタが実行される前に実行される
  • コンストラクタをオーバーロードしても、呼ばれる親クラスのコンストラクタはデフォルトコンストラクタ。
  • オーバーライドしていないメソッドは親クラスのメソッドがそのまま呼ばれる
  • オーバーライドしているメソッドは子クラスのメソッドが呼ばれ、親クラスのメソッドは呼ばれない

サブクラスからスーパークラスを呼ぶ

サブクラスからスーパークラスを呼びたい場合は、子クラスの引数ありコンストラクタに、明示的に記述すれば、引数ありの親クラスコンストラクタが呼ばれるようになります。

(引数ありコンストラクタを明示的に呼ぶ)

//コンストラクタ(引数あり)
public SubClass(String str){
  super(str);
  System.out.println("SubClass-con2");
}

また、子クラスのメソッド内に明示的に親クラスのメソッドを呼ぶように記述すれば、オーバーライドする前の親クラスのメソッドを呼ぶことも出来ます。

(オーバーライド元のメソッドを明示的に呼ぶ)

//メソッド2をオーバーライド
public void m2(){
  super.m2();
  System.out.println("sub-m2");
}

継承のまとめ

Javaの継承の特徴やルールをまとめると以下のようになります。

  • 継承にはextendsキーワードを使用する
  • Javaでは単一継承のみが許可されている(多重継承は不可)
  • 同じシグニチャのメソッドを子クラスで定義すると親クラスのメソッドを上書きしたことになる。(これをオーバーライドと呼ぶ)
  • オーバーライドしたとしても、superキーワードを使用して親クラスのメソッドを呼ぶことも可能。
  • 子クラスをインスタンス化したときは、親クラスの引数なしコンストラクタが実行された後に子クラスのコンストラクタが実行される。

コメント

タイトルとURLをコピーしました