継承

継承(inheritance)とは、あるクラスの特徴(フィールドとメソッド)を引き継ぎながら、継承元の特徴を一部変更したり、新たな特徴を付加して新しいクラスを作りだす仕組みです。継承によりソフトウェアでも実物の部品と同じようにパーツからユニット、コンポーネントを作る事ができ、階層構造を持ったプログラム部品を作ることによりプログラムの生産性が大きく向上します。

例えば類似のクラスがいくつか必要な場合、共通部分をコピーしていくつかのクラスを作ることも出来ますが、もしコピーした共通部分を変更したくなった場合、コピーした全ての共通部分を修正しなければいけません。これに対し継承を使って類似クラスを作れば、共通部分をクラスとして作りそのクラスを継承すれば、類似クラスが作れます。そして、共通部分の変更が必要になった場合、継承元のクラスを修正しさえすれば、継承して作った全ての類似クラスは何も手をかけることなく共通部分が変更されたものとして使うことが出来ます

継承の元になるクラスをスーパークラス、スーパークラスを継承したクラスはサブクラスと呼びます。

継承の書式

クラス宣言でスーパークラスを明示します。
class サブクラス名 extends スーパークラス名 { }

スーパークラス
通常のクラスとして記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class NormalTV {
     
    void on() {
        System.out.println("\t電源を入れます。");
    }
    void off() {
        System.out.println("\t電源を切ります。");
    }
    void display() {
        System.out.println("\t番組を視聴します。");
    }
    void channelChange() {
        System.out.println("\tチャネルを切り替えます。");
    }
    void functions() {
        on();
        off();
        display();
        channelChange();
    }
}

サブクラス
スーパークラスの明示と共にスパークラスとのフィールドおよびメソッドの差分を記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SmartTV extends NormalTV {
     
    void internet() {
        System.out.println("\tインターネットにアクセスします。");
    }
    void recode() {
        System.out.println("\t番組を録画します。");
    }
    void dvd() {
        System.out.println("\tDVDを再生します。");
    }
    void functions() {
        super.functions();
        internet();
        recode();
        dvd();
    }
}

スーパークラス、サブクラスを利用する処理

1
2
3
4
5
6
7
8
9
10
11
12
public class InheritanceSample {
    public static void main(String[] args) {
 
        NormalTV ntv = new NormalTV();
        SmartTV stv = new SmartTV();
         
        System.out.println("NomalTVの機能:");
        ntv.functions();
        System.out.println("SmartTVの機能:");
        stv.functions();
    }
}

実行結果

>java InheritanceSample
NomalTVの機能:
        電源を入れます。
        電源を切ります。
        番組を視聴します。
        チャネルを切り替えます。
SmartTVの機能:
        電源を入れます。
        電源を切ります。
        番組を視聴します。
        チャネルを切り替えます。
        インターネットにアクセスします。
        番組を録画します。
        DVDを再生します。
 
>

これらのクラスの継承関係をクラス図で表すと

継承関係はサブクラスからスーパークラスに白い三角形の実線矢印を引きます。(親を指し示す)

なお、継承によってサブクラスはスーパークラスの特徴を引き継ぎますが、次の2つは引き継げません。

コンストラクタ
privateなフィールドやメソッド

サブクラスはスーパークラスのコンストラクタを引き継がないという事は、サブクラスは独自のコンストラクタを持たなければなりません。そして、サブクラスはスーパークラスとサブクラスの付加部分で構成されているので、サブクラスのインスタンスを作るためにはスーパークラスとサブクラス両方のコンストラクタを持たせる必要があります

そこで、サブクラスでコンストラクタを独自に定義する場合はスーパークラスが持つコンストラクタが先に実行され、サブクラスが持つコンストラクタが後から実行されるようにサブクラスのコンストラクタの先頭に、スーパークラスのコンストラクタを呼び出すコードsuper();を追加しなければいけません。

一方、デフォルトコンストラクタを使う場合はコンパイラが自動的にサブクラスのデフォルトコンストラクタの先頭でスーパークラスのデフォルトコンストラクタを呼ぶコードを追加します。

なお、Javaではクラスの多重継承は禁止されています。(インタフェースはクラスではないので、多重実現は認められています。)

また、継承関係にあるサブクラスのインスタンスの中身は、スーパークラスとサブクラス(スーパークラスとの差分)のインスタンスで構成されています。そして、各インスタンスは独立しておりJVMからは別々に扱われています。従って、スーパークラスとサブクラスで同名のインスタンス変数があったとしても、それらは異なるものです。
そこで、メソッドがインスタンス変数を扱う場合、同一クラス内のインスタンス変数であればthis.を、サブクラスからスーパークラスのインスタンス変数であればsuper.をインスタンス変数名の前に付けて記述します。

プログラムの部品化に戻る