Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
60
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

[Java]クラスの継承とコンストラクタ

コンストラクタとは

あるクラスがnewされた直後に自動的に実行されるメソッド。

public class Hello {
    public Hello() {
        // Helloクラスがnewされるとここの内容が実行されるよ
    }
}

オーバーロードして複数定義もできる。

public class Hello {
    public Hello() {
        // new Hello();で実行される部分
    }

    public Hello(int x) {
        // new Hello(x);で実行される部分
    }
    ...
}

暗黙のコンストラクタ

本来、全てのクラスは1つ以上のコンストラクタ定義を持っている必要がある。
クラスに1つもコンストラクタが定義されていない場合に限り、引数なし、処理なしのコンストラクタが自動で定義される。

public class Hello {
    ...
}

これは

public class Hello {
    public Hello() {
    }
    ...
}

これと同じ。

明示的定義と暗黙的定義

1つでもコンストラクタ定義を記述すると、空コンストラクタは自動で定義されない

public class Hello {
    public Hello(int x) {
        ...
    }
}

上の状態でnew Hello();はできない。

コンストラクタから(同じクラスの)別のコンストラクタを呼び出す

コンストラクタから別のコンストラクタを呼び出す場合はthis()を使う。
呼び出しはコンストラクタの先頭で行わなければならない。

public class Hello {
    public Hello(String s) {
        ...
    }
    public Hello() {
        this("default"); // 必ず先頭で呼び出す
        ...
    }
}

継承とコンストラクタ

以下、簡便のため子クラスのコンストラクタを「子コンストラクタ」、親クラスのコンストラクタを「親コンストラクタ」と記述する。

子クラスにおける明示的なコンストラクタ

本来、子コンストラクタは先頭で親コンストラクタを呼び出さなければならない。

public class Child extends Parent {
    public Child(){
        super(); // 必ず先頭で呼び出す
        ...
    }
}

このとき親コンストラクタの引数などは関係ない。
親コンストラクタが複数ある場合はどれを呼んでもいい。

public class Child extends Parent {
    public Child(){
        super(0);
        ...
    }
}
public class Child extends Parent {
    public Child(){
        super("default");
        ...
    }
}

こんなのもあり得る。ただし先頭以外で親コンストラクタを呼び出すことは出来ない

例えば以下のように2つのコンストラクタを呼び出すことはできない。

Error
public class Child extends Parent {
    public Child(){
        super();
        ...
        super("default"); // 呼び出しが先頭でないため不可
    }
}

子クラスにおける暗黙的なコンストラクタ

子コンストラクタで親コンストラクタが呼ばれていない場合、引数なしの親コンストラクタが自動で呼び出される。

public class Child extends Parent {
    public Child(){
        ...
    }
}

これは

public class Child extends Parent {
    public Child(){
        super();
        ...
    }
}

これと同じ。

子クラスのコンストラクタ自体を定義していない場合、空の子コンストラクタが自動定義され、さらに親コンストラクタが自動で呼び出される。

public class Child extends Parent {

}

これを

public class Child extends Parent {
    public Child(){
    }
}

こうして

public class Child extends Parent {
    public Child(){
        super();
    }
}

こうじゃ。

子クラスにおける暗黙的なコンストラクタの注意点

子コンストラクタに引数があってもなくても、親コンストラクタ呼び出しを省略した場合は引数なしのsuper()が自動で呼び出される。

以下の例を考える。

public class Parent {
    protected String name;
    public Parent(String s) {
        this.name = s;
    }
}
Error
public class Child extends Parent {
    public Child(String s) {
        this.name += "ちゃん";
    }
}

このとき、子コンストラクタの先頭ではsuper(String)ではなくsuper()を呼び出そうとするので、エラーとなる。
子クラスの先頭でsuper(String)の呼び出しを明示するか、親クラスに引数なしの場合のコンストラクタを追加する必要がある。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
60
Help us understand the problem. What are the problem?