
Java入門|インターフェイスで実現する多重継承
親は1人でも、受け継ぐ約束は複数にできる。
インターフェイスを使うと、Javaでは多重継承の考え方を安全にわかりやすく表現できる。
ここまで、クラスの継承、抽象クラス、インターフェイスを順番に見てきました。
すると次に気になってくるのが、複数の性質を1つのクラスにどう持たせるのか という点です。
現実の世界では、1つのものがいくつもの特徴をあわせ持つことはよくあります。
ドラゴンボールで考えても、
- 戦士である
- 空を飛べる
- 気を使える
- 特定の能力のルールを守る
といったように、1人のキャラクターが複数の性質や約束を同時に持つことは自然です。
ところが、Javaのクラスの継承では、1つのクラスが複数のスーパークラスを同時に持つことはできません。つまり、クラスそのものの多重継承は認められていません。
そこで登場するのがインターフェイスです。
Javaでは、クラスの多重継承はできなくても、2つ以上のインターフェイスを実装すること はできます。これによって、複数の「約束」や「メソッド名のルール」を、1つのクラスに同時に持たせることができます。
ドラゴンボールでたとえると、これは
「この戦士は戦士としてのルールも守るし、気を使う者としてのルールも守るし、空を飛べる者としてのルールも守る」
と宣言するようなものです。
今回は、「インターフェイスで実現する多重継承」を、ドラゴンボールの世界観で置きかえながら、やさしく丁寧に整理していきます。特に、
- Javaでクラスの多重継承ができない理由
- それでも複数のインターフェイスを実装できる意味
- 2つ以上のインターフェイスを実装したクラスでは何が必要か
- なぜこれが多重継承の一部を実現していると言えるのか
を順番に見ていきます。
Javaではクラスの多重継承はできない
まずは出発点をはっきりさせましょう。
Javaでは、1つのクラスが2つ以上のスーパークラスを同時に継承することはできません。
たとえば、ドラゴンボール風に
- Warrior クラス
- KiUser クラス
のような2つのクラスがあったとして、その両方を親に持つ1つのクラスを作ることはできません。
つまり、考え方としてはこういうことです。
class Saiyan extends Warrior, KiUser
{
...
}このようなクラス宣言はJavaでは認められません。
親クラスは1つだけです。
ドラゴンボールで言えば、1人の戦士クラスが
「戦士クラス」と「別の基本クラス」を同時に親として持つような複雑な系譜は作れない、ということです。
それでも複数の性質を持たせたい場面はある
ここで困るのは、現実には1つのクラスが複数のルールを持ちたい場面が多いことです。
ドラゴンボールで考えると、たとえばベジータは
- サイヤ人である
- 戦闘情報を表示できる
- 気を使える
- 飛行もできる
といった複数の特徴を持っています。
もしクラスの継承だけに頼るなら、こうした複数の側面を表現しにくくなります。
そこでJavaは、クラスの多重継承は認めない代わりに、インターフェイスの複数実装 を用意しています。
つまりJavaは、
- クラスの親は1つだけにして構造を整理する
- でも約束や能力のルールは複数持てるようにする
という形で、わかりやすさと柔軟さを両立しているわけです。
インターフェイスの多重実装とは何か
Javaでは、1つのクラスが2つ以上のインターフェイスを実装できます。
このとき使うのが implements です。インターフェイス名をカンマで並べれば、複数のインターフェイスを同時に実装できます。
形としてはこうです。
class クラス名 implements インターフェイス名1, インターフェイス名2
{
...
}これは、ドラゴンボール風に言えば
「この戦士クラスは、インターフェイス名1の約束も守るし、インターフェイス名2の約束も守る」
と宣言しているようなものです。
つまり、複数の親クラスを持つのではなく、複数の「メソッド名の約束」を同時に引き受けるわけです。
なぜこれが多重継承の一部と言えるのか
本文では、2つ以上のインターフェイスを実装することによって、多重継承のしくみの一部を実現できると説明されています。
ここで大切なのは、「クラスそのものを複数継承する」のではなく、メソッド名の約束を複数受け継ぐ という点です。
たとえば、
- iWarrior が vShow() を持つ
- iMaterial が mShow() を持つ
とします。
それらを1つのクラスが両方実装すると、そのクラスは
- vShow()
- mShow()
の両方を必ず定義しなければなりません。
つまり、2つのインターフェイスが持っていたメソッド名のルールを、1つのクラスがまとめて受け継ぐことになります。
ドラゴンボールでいえば、
- 戦士として見せるためのルール
- 材質や属性を見せるためのルール
の両方を、1人のキャラクターが同時に引き受けるようなものです。
だから、これは「複数のクラスを継承する」わけではないけれど、複数のインターフェイスが定めるメソッドの名前と役割を重ねて受け継ぐ という意味で、多重継承の考え方の一部を実現していると言えます。
サンプルプログラム:2つ以上のインターフェイスを実装する例
ここでは、ドラゴンボール風のクラスで、2つ以上のインターフェイスを実装する例を見ていきます。
iWarrior と iArmor を Saiyan クラスが実装する形を用います。内容は、戦士としての表示メソッドと、防具や材質の情報を見せるメソッドを、1つのクラスが両方持つ流れです。
ファイル名:Sample4.java
interface iWarrior
{
void wShow();
}
interface iArmor
{
void aShow();
}
class Saiyan implements iWarrior, iArmor
{
private String name;
private int power;
public Saiyan(String n, int p)
{
name = n;
power = p;
System.out.println(name + " 戦闘力" + power + "のサイヤ人を作成しました。");
}
public void wShow()
{
System.out.println("サイヤ人の名前は" + name + "です。");
System.out.println("戦闘力は" + power + "です。");
}
public void aShow()
{
System.out.println("サイヤ人の防具はサイヤアーマーです。");
}
}
class Sample4
{
public static void main(String[] args)
{
Saiyan warrior1 = new Saiyan("ベジータ", 18000);
warrior1.wShow();
warrior1.aShow();
}
}実行結果
ベジータ 戦闘力18000のサイヤ人を作成しました。
サイヤ人の名前はベジータです。
戦闘力は18000です。
サイヤ人の防具はサイヤアーマーです。このプログラムで見てほしいところ
このプログラムでは、Saiyan クラスが 2 つのインターフェイスを実装しています。
class Saiyan implements iWarrior, iArmorここで言っているのは、
- iWarrior の約束も守る
- iArmor の約束も守る
ということです。
そのため Saiyan クラスは、どちらのインターフェイスが持つメソッドも、きちんと定義しなければなりません。
今回なら、
- iWarrior の wShow()
- iArmor の aShow()
の両方を定義しています。
ここがとても大切です。
インターフェイスを複数実装するということは、複数の約束を同時に引き受けることなのです。
wShow() と aShow() は何を表しているのか
この例では、2つのインターフェイスが別々の役割を持っています。
| インターフェイス | メソッド | 表している役割 |
|---|---|---|
| iWarrior | wShow() | 戦士としての情報を見せる |
| iArmor | aShow() | 防具や材質の情報を見せる |
つまり Saiyan クラスは、
- 戦士としての見せ方
- 防具情報の見せ方
の両方を持つことになります。
ドラゴンボールで言えば、ベジータは
- 戦士として名乗れる
- さらにサイヤアーマーについても見せられる
ということです。
このように、1つのクラスが複数の「能力の約束」をまとめて持てるのが、インターフェイスの多重実装の強みです。
なぜクラスの多重継承より扱いやすいのか
クラスの多重継承をしてしまうと、親クラスどうしが持つフィールドやメソッドの関係が複雑になりやすいです。
一方でインターフェイスは、主に「メソッド名の約束」を表すものなので、役割をきれいに分けやすくなります。
つまり、
- クラスの継承は共通の土台を受け継ぐ
- インターフェイスは能力や約束を追加する
というふうに役割分担できます。
ドラゴンボールで考えるなら、
- クラスは「サイヤ人という種族・型」
- インターフェイスは「戦士として表示できる」「防具情報を見せられる」
といった能力ルールです。
この整理があるから、Javaではクラス構造が過度に複雑にならずにすみます。
インターフェイスの複数実装はどんな場面で便利か
インターフェイスの多重実装は、1つのクラスに複数の役割を持たせたいときに便利です。
たとえばドラゴンボール風に考えると、
- iWarrior で戦士としての共通ルールを持たせる
- iArmor で防具や材質の表示ルールを持たせる
- 将来的には iFlyable のような飛行ルールも足せる
というふうに、必要な約束を増やしていけます。
すると、クラスは1つの親クラスを保ちながら、能力や役割の面では柔軟に広げられます。
これが、インターフェイスによって多重継承の考え方を安全に取り入れているポイントです。
抽象クラスとの違いも意識しておきたい
ここで、抽象クラスとインターフェイスの違いも整理しておくと理解しやすくなります。
| 比較項目 | 抽象クラス | インターフェイス |
|---|---|---|
| 役割 | 共通の土台 | 共通の約束 |
| 通常フィールド | 持てる | 原則として持てない |
| 通常メソッド | 持てる | 原則として処理を書かない |
| 継承・実装 | extends で1つだけ | implements で複数可 |
つまり、
- 抽象クラスは「何者か」を表しやすい
- インターフェイスは「何ができるか」を表しやすい
という違いがあります。
だから、インターフェイスの多重実装は、種族や基本の型を複数持つのではなく、能力や役割の約束を複数持つものとして理解すると整理しやすいです。
オブジェクト指向らしい自然な設計につながる
本文では、スーパークラス・抽象クラス・インターフェイスの変数を使えば、それらの機能を継承するサブクラスのオブジェクトをまとめて扱えることが説明されています。
インターフェイスの多重実装も、この流れの中でとても自然です。
ドラゴンボールで言えば、現実のキャラクターたちにも
- 種族としての分類
- できることの分類
- 装備や属性の分類
が同時にあります。
Javaのインターフェイスは、その「できること」や「守る約束」を自然にプログラムへ落とし込むためのしくみです。
そのため、コードの構造が現実の考え方と対応しやすくなります。
図でインターフェイスによる多重継承を整理する
このテーマは、2つのインターフェイスから1つのクラスへ約束が集まる図にすると、とても理解しやすくなります。

上部には 2 つのインターフェイスがあります。
iWarrior は wShow()、iArmor は aShow() という約束を持っています。
中央下の Saiyanクラス は、その両方を実装しているので、2つの約束を同時に引き受けています。
そのため、wShow() と aShow() の両方を定義しなければなりません。
この図から、Java ではクラスの多重継承はできなくても、インターフェイスを使えば複数のメソッドの約束を1つのクラスへ集められることが見えてきます。
ドラゴンボールで感覚的に整理する
最後に、ドラゴンボールの感覚で整理してみましょう。
Javaでは、1人の戦士クラスが同時に複数の親クラスを持つことはできません。
これはクラスの多重継承が禁止されているからです。
でも、1人の戦士が複数の能力や約束を持つことは、現実にも自然です。
そこでインターフェイスを使うと、
- 戦士としての約束
- 防具情報を見せる約束
- ほかの能力の約束
を、1つのクラスが同時に引き受けられます。
つまりインターフェイスによる多重実装は、
親クラスを増やすのではなく、守るべき約束を増やすことで、多重継承の考え方を表現する仕組み
です。
この感覚がつかめると、Java がなぜクラスの多重継承を認めず、それでもインターフェイスで柔軟さを残しているのかが、とても自然に見えてくるようになります。
