導入
抽象クラスもインタフェースも「実装をサブクラス/実装クラスに強制する型」ですが、使い分けの基準を整理しておきましょう。両方を組み合わせて使うこともできます。
説明
| 抽象クラス | インタフェース | |
|---|---|---|
| 継承/実装できる数 | 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 + "が泳ぐ");
}
}
Penguin は Animal(is-a、共通のフィールド name を継承)を extends しつつ、Swimmable(can-do)を implements しています。extends と implements は同時に使え、extends は必ず implements より前に書きます。
やってみよう
下のエディタで Penguin に別のインタフェース(例えば Walkable)を追加で実装してみましょう。
演習
Duck extends Animal implements Swimmable というクラスを作ってください。コンストラクタで name を受け取り super(name) で初期化し、sound() で name + "が鳴く"、swim() で name + "が泳ぐ" と表示してください。main で new Duck("アヒル") を作り、sound() と swim() を呼んでください。
ヒント1を見る
class Duck extends Animal implements Swimmable { Duck(String name) { super(name); } ... }。
ヒント2を見る
sound() と swim() はどちらも Penguin の実装と同じ書き方です。