👾

【Java】継承とコンストラクタの呼び出し順

2021/09/14に公開

この記事でわかること

  • 継承について
  • 継承した際のコンストラクタの挙動・呼び出し順について

継承とは

親クラス(スパークラス)から フィールドメソッド を受け継ぐこと。

extendsを使ってスーパークラスを継承する

一般化

class Superclass {
  ...
}

class Subclass extends Superclass {
  ...
}

フィールドの継承

具体例

class Superclass {
  String text;
}

class Subclass extends Superclass {
  public static void main(String[] args) {
    Subclass sub = new Subclass();
    sub.text = "Hello, World";
		System.out.println(sub.text);
		// => Hello, World
	}
}

Subclassで textフィールドを定義していなくても Superclassで定義してあるので利用可能

メソッドの継承

具体例

class Superclass {
  String text;

	void setText(String text) {
		this.text = text;
	}

	void appendText(String text) {
    this.text += text;
	}
}

class Subclass extends Superclass {
  public static void main(String[] args) {
    Subclass sub = new Subclass();
		sub.setText("Hello");
		sub.appendText(", World");
		System.out.println(sub.text);
		// => Hello, World
	}
}

Subclassで setTextmethodや appendTextmethodを定義していなくても、スーパークラスに定義してあるので、Subclassのインスタンス(オブジェクト)に対して命令を出すことが可能

コンストラクタの継承について

コンストラクタは継承されない。なので、サブクラスでコンストラクタは定義する必要

スーパークラスとサブクラスとは何か

すでに スーパークラス(Superclass)サブクラス(Subclass) というワードが出てきているが、そもそもスーパークラスとサブクラスとは何か?

継承元のクラスのことを スーパークラス。 スーパークラスから見た継承先のクラスのことを サブクラス という。

// 継承元
class Superclass {
  ...
}

// Superclassから見た継承先(Superclassを継承している)
class Subclass extends Superclass {
  ...
}

1つのサブクラスに対してスーパークラスは1つと決まっている

【本題】コンストラクタの呼び出し順

継承はフィールドとメソッドは継承されるが、コンストラクタは継承されないという話は前の項目でしました。なのでサブクラスでもコンストラクタは定義する必要があります。そこで注意点すべき点として、サブクラスでコンストラクタを定義するとスーパークラスのコストラクタも呼び出されることです。

上記をもとに、コンストラクタの呼び出し順を見ていきます。

Superclass

class Superclass {
  Superclass() {
    System.out.println("1: 引数なし");
  }

  Superclass(String text){
    System.out.println("2: " + text);
  }
}

Subclass

class Subclass extends Superclass {
  Subclass() {
    System.out.println("3: 引数なし");
  }

  Subclass(int num) {
    System.out.println("4: 引数あり" + num);
  }

  Subclass(String text) {
    super(text);
    System.out.println("5: " + text);
  }

  public static void main(String[] args){
    System.out.println("==========");
    new Superclass();

    System.out.println("==========");
    new Subclass();

    System.out.println("==========");
    new Superclass("引数あり");

    System.out.println("==========");
    new Subclass(123);

    System.out.println("==========");
    new Subclass("引数あり");
  }
}

出力結果

==========
1: 引数なし
==========
1: 引数なし
3: 引数なし
==========
2: 引数あり
==========
1: 引数なし
4: 引数あり123
==========
2: 引数あり
5: 引数あり

上記からわかること

  • Subclassのコンストラクタが呼び出されるタイミングでSuperclassの引数なしコンストラクタが先に呼び出される
  • 明示的にSuperclassのコンストラクタを呼び出すには super() を利用する
  • Superclassの引数ありコンストラクタを呼びたいときは super() を利用する

Discussion