本文へスキップ
BecomeCoder

Javaオブジェクト指向コース · 第5章 抽象クラスとインタフェース ― 型で「約束」する · レッスン20

抽象クラス vs インタフェース ― 使い分け

ブラウザで完結

導入

抽象クラスもインタフェースも「実装をサブクラス/実装クラスに強制する型」ですが、使い分けの基準を整理しておきましょう。両方を組み合わせて使うこともできます。

説明

抽象クラスインタフェース
継承/実装できる数1つだけ(extendsは1本道)複数(implementsはいくつでも)
フィールドを持てるか持てる(状態を共有できる)基本的に持てない
関係の種類is-a(〜の一種)can-do(〜ができる)
使いどころ共通のフィールド・処理をまとめたいまったく別の種類のクラスに共通の「できること」を持たせたい

抽象クラスとインタフェースは 組み合わせて 使うこともできます。「〇〇は動物の一種(is-a)」は抽象クラスで、「かつ泳げる(can-do)」はインタフェースで表現します。

public class Main {
    public static void main(String[] args) {
        Penguin p = new Penguin("ペンギン");
        p.sound();
        p.swim();
    }
}

interface Swimmable {
    void swim();
}

abstract class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    abstract void sound();
}

class Penguin extends Animal implements Swimmable {
    Penguin(String name) {
        super(name);
    }

    @Override
    void sound() {
        System.out.println(name + "が鳴く");
    }

    @Override
    public void swim() {
        System.out.println(name + "が泳ぐ");
    }
}

PenguinAnimal(is-a、共通のフィールド name を継承)を extends しつつ、Swimmable(can-do)を implements しています。extendsimplements は同時に使え、extends は必ず implements より前に書きます。

やってみよう

下のエディタで Penguin に別のインタフェース(例えば Walkable)を追加で実装してみましょう。

演習

Duck extends Animal implements Swimmable というクラスを作ってください。コンストラクタで name を受け取り super(name) で初期化し、sound()name + "が鳴く"swim()name + "が泳ぐ" と表示してください。mainnew Duck("アヒル") を作り、sound()swim() を呼んでください。

ヒント1を見る

class Duck extends Animal implements Swimmable { Duck(String name) { super(name); } ... }

ヒント2を見る

sound()swim() はどちらも Penguin の実装と同じ書き方です。

実際に動かしてみよう

下のエディタにJavaを書いて「実行」を押すと、学習用シミュレータが System.out.println の出力を表示します(本物のJVMではなく、教材の範囲を再現した軽量エンジンです)。クラス・継承・コレクションなども動きます。Scanner で入力を読む例は「標準入力」欄に値を入れてください。本文の例を書き換えて動かしてみましょう(Stream・ラムダ・スレッド・ファイル入出力など一部の機能は対象外です)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。