😸

[Java]クラスの継承

に公開

はじめに

ここでは以下についてまとめています。

  • クラスの継承
  • オーバーライド
  • super
  • 抽象クラス(abstract)

クラスの継承

既存のクラス(親クラス/スーパークラス)を拡張して、新しいクラス(子クラス/サブクラス)を作る仕組みです。コードの再利用性や拡張性を高めることができます。
すべてのクラスは、暗黙的にjava.lang.Objectクラスを継承しています。

継承

あるクラスが他のクラスを「継承(inherit)」することで、そのクラスのフィールドやメソッドを引き継ぐことができます。
また、親クラスの機能を再利用・拡張・上書き(オーバーライド)できます。
Javaでは単一継承のみであり、1つのクラスだけ継承可能です。

基本構文

extendを使用して継承します。

class 親クラス {
    // フィールドやメソッド
}

class 子クラス extends 親クラス {
    // 継承されたものを使ったり、独自の機能を追加したりできる
}

継承の例

DogAnimalという親クラスを継承しています。

class Animal {
    void speak() {
        System.out.println("動物が鳴く");
    }
}

class Dog extends Animal {
    void wagTail() {
        System.out.println("しっぽを振る");
    }
}
Dog dog = new Dog();
dog.speak();    // 動物が鳴く(親クラスのメソッド)
dog.wagTail();  // しっぽを振る(子クラスの独自メソッド)

オーバーライド

子クラスが、親クラスのメソッドを上書きして独自の動作に変更できます。

class Animal {
    void speak() {
        System.out.println("動物が鳴く");
    }
}

class Dog extends Animal {
    @Override
    void speak() {
        System.out.println("ワンワン!");
    }
    void wagTail() {
        System.out.println("しっぽを振る");
    }
}

以下のようにAnimal animal = new Dog();とするとanimal.wagTail();はコンパイルエラーになります。
今回Animal animal = new Dog();としているのは抽象的に扱いたいためです(ポリモーフィズム)。
wagTail()を使用したいのであれば、Dog dog = new Dog();とするとdog.wagTail(); // しっぽを振るが出力されます。

Animal animal = new Dog();
animal.speak(); // ワンワン!(子クラスの実装が使われる)

animal.wagTail(); // コンパイルエラー:Animal型に wagTail() は存在しない

superキーワード

superを使うと、親クラスのコンストラクタやメソッドにアクセスできます。
以下は親クラスのメソッドを呼び出しています。

class Animal {
    void speak() {
        System.out.println("動物が鳴く");
    }
}

class Dog extends Animal {
    @Override
    void speak() {
        super.speak(); // 親の speak を呼ぶ
        System.out.println("ワンワン!");
    }
}

親クラスのコンストラクタを呼び出す際は以下のようにします。

class Animal {
    Animal(String name) {
        System.out.println("Animal: " + name);
    }
}

class Dog extends Animal {
    Dog() {
        super("ポチ"); // 親クラスのコンストラクタを呼ぶ
    }
}

抽象クラス

共通の機能の定義と、共通インターフェースの提供を目的としたクラス設計の一部です。直接インスタンス化できないクラスで、他のクラスに継承されることを前提としています。
以下のような場合に使用します。

  • 共通の機能を定義しつつ、一部の振る舞いはサブクラスに任せたいとき
  • ポリモーフィズム(多態性)を活用したいとき
  • インターフェースよりも共通実装を多く持たせたいとき

基本構文

abstractを使用します。

abstract class クラス名 {
    // フィールド、コンストラクタ、具象メソッド、抽象メソッドなど
}

抽象クラスの例

abstract class Animal {
    // 抽象メソッド(中身なし)
    abstract void speak();

    // 通常のメソッド(中身あり)
    void sleep() {
        System.out.println("すやすや眠る");
    }
}

// 継承クラス
class Dog extends Animal {
    @Override
    void speak() {
        System.out.println("ワンワン!");
    }
}
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        dog.speak();  // → ワンワン!
        dog.sleep();  // → すやすや眠る
    }
}
特徴 説明
abstract キーワード クラスとメソッドに使う
インスタンス化不可 new Animal() はできない(抽象クラス単体では使えない)
抽象メソッドを含める 中身のないメソッドを定義して子クラスに実装を強制
通常のメソッドも定義可 具象メソッド(sleepなど)も持てる
フィールドやコンストラクタも持てる 他のクラスと同じように持てる
子クラスは extends で継承 抽象メソッドをすべてオーバーライドする必要あり

Discussion