Java入門

【Java入門】継承

2021年4月30日

はじめに

前回の記事では、Javaのアクセス修飾子について紹介しました。

本記事では、Javaの継承について紹介します。

継承とは

継承とは、クラスが持っているメンバ(フィールドやメソッド)を別のクラスに引き継がせることです。継承元のクラスをスーパークラス(または親クラス)、引き継いだクラスをサブクラス(または子クラス)といいます。

継承はオブジェクト指向の大きな特徴の一つです。

※オブジェクト指向の3大要素は「継承」「ポリモーフィズム(多態性)」「カプセル化」

サブクラスを作成するには「extends」(読み:エクステンズ)を使用します。次のように「extends」の前にサブクラス名(子クラス名)、後にスーパークラス名(親クラス名)を指定します。

extendsの使い方
継承を使うメリットって何ですか?
それでは、継承を利用する・しないでどのような違いがあるか、継承のメリットを説明していきます。

スポンサーリンク

継承を利用しない場合の例

まずは、継承を利用しない場合の説明です。

例えば次のような2つのクラスがあるとします。

[新車クラス]

public class NewCar {
    /**
     * 製造元
     */
    private static final String MANUFACTURER = "○○自動車";
    
    /**
     * 製造元と販売価格を出力する
     * @param price 販売価格
     */
    private void print(int price) {
        System.out.println("製造元は" + MANUFACTURER);
        System.out.println("販売価格は" + price + "円");
    }
    
    /**
     * 新車の製造元と販売価格を出力する
     * @param price 販売価格
     */
    public void printNewCar(int price) {
        System.out.println("新車です");
        print(price);
    }
}

[中古クラス]

public class OldCar {
    /**
     * 製造元
     */
    private static final String MANUFACTURER = "○○自動車";
    
    /**
     * 製造元と販売価格を出力する
     * @param price 販売価格
     */
    private void print(int price) {
        System.out.println("製造元は" + MANUFACTURER);
        System.out.println("販売価格は" + price + "円");
    }
    
    /**
     * 中古車の製造元と販売価格を出力する
     * @param price 販売価格
     */
    public void printOldCar(int price) {
        System.out.println("中古車です");
        print(price);
    }
}

この2つのクラスは、どちらも車に関連するクラスであり、以下の内容がまったく同じです。

継承を使わない場合

同じ内容のソースコードを色々な個所に書くと、修正する際に複数の個所を直す必要があり、保守性が悪くなります。

そのため、共通的な部品は「共通クラス」として管理するか「継承」して管理します。(例えば、色々なクラスで使う共通的な部品であれば共通クラス、車クラスの共通部品であれば車の親クラスで管理など)

確かに、同じソースコードが色々な個所に書かれているプログラムは、修正が大変なんだよな・・・

継承を利用する場合の例

それでは、継承を利用した場合の例を説明します。

まず車の共通的な機能は、スーパークラス(親クラス)で定義します。

[車の基本クラス]

public class BaseCar {
    /**
     * 製造元
     */
    private static final String MANUFACTURER = "○○自動車";
    
    /**
     * 製造元と販売価格を出力する
     * @param price 販売価格
     */
    protected void print(int price) {
        System.out.println("製造元は" + MANUFACTURER);
        System.out.println("販売価格は" + price + "円");
    }
}

そして、サブクラス(子クラス)でサブクラス独自の処理を実装します。

[新車クラス]

public class NewCar extends BaseCar {
    
    /**
     * 新車の製造元と販売価格を出力する
     * @param price 販売価格
     */
    public void printNewCar(int price) {
        System.out.println("新車です");
        print(price);
    }
}

[中古クラス]

public class OldCar extends BaseCar {
    
    /**
     * 中古車の製造元と販売価格を出力する
     * @param price 販売価格
     */
    public void printOldCar(int price) {
        System.out.println("中古車です");
        print(price);
    }
}

上記例では、「新車クラス」と「中古クラス」は「車の基本クラス」を継承しています。

継承を使うことで、車の共通的な機能はスーパークラス(親クラス)で管理し、サブクラス(子クラス)では、サブクラス独自の機能を実装するだけです。

継承を利用することで、何度も同じソースコードを書かずに済み、読みやすいソースコードが書けます。

ただし、継承もやりすぎると"保守性"や"可読性"が悪くなる場合もあるので、しっかりと検討したうえで継承を使うことが大切です。

終わりに

本記事では、Javaの継承について紹介しました。

Javaには、継承をより便利にする「オーバーライド」や「抽象クラス(abstract)」といった機能もあります。

次回の記事では、Javaの「オーバーライド」について紹介します。

helpful