
Java道|インターフェイスで共通ルールを作る
「何者か」ではなく、「何ができるか」でクラスをつなぐ。
インターフェイスを理解すると、共通ルールを守るクラスを、すっきり自然にまとめられるようになります。
12章では、抽象クラスに続いて、もうひとつ大切なしくみである インターフェイス を学びます。
インターフェイスは、見た目はクラスに少し似ています。
しかし、役割はかなりはっきりしています。
インターフェイスは、具体的な状態をたくさん持つためのものではありません。
主な役割は、
この型に属するものは、このメソッドを必ず持っている
という共通ルールを決めることです。
鬼滅の刃風にたとえると、インターフェイスは「剣士なら show() で情報を示せること」「飛行できる者なら fly() を持つこと」のような、能力や役割の約束に近いです。
クラスや抽象クラスは、WaterSlayer や MedicalSlayer のように「何者か」を表しやすいです。
一方、インターフェイスは、iSlayer のように「何ができるか」「どんな約束を守るか」を表します。
| 種類 | 表しやすいもの | 鬼滅の刃風のイメージ |
|---|---|---|
| クラス | 具体的な存在 | 水の剣士、支援剣士 |
| 抽象クラス | 共通の土台 | 剣士としての基本設計 |
| インターフェイス | 能力や約束 | 情報を表示できる、任務を遂行できる |
Javaでは、クラスがインターフェイスを実装することで、複数のクラスに同じメソッド名の約束を持たせられます。
その結果、見た目や中身が違うクラスでも、同じインターフェイスを実装していれば、同じ型としてまとめて扱えるようになります。
インターフェイスとは何か
インターフェイスは、class の代わりに interface を使って宣言する特別な型です。
interface iSlayer
{
void show();
}この iSlayer インターフェイスは、
iSlayer を実装するクラスは、必ず show() を持ちなさい
という約束を表しています。
ここで大切なのは、show() の中身はまだ決まっていないことです。
つまり、インターフェイスは処理の中身を作る場所というより、
メソッド名と役割のルールを決める場所
です。
鬼滅の刃風にたとえると、iSlayer は「この印を持つ剣士は、自分の情報を示す show() を必ず使える」という隊の共通規則です。
WaterSlayer なら、水の呼吸や名前を表示する show() を作ります。
MedicalSlayer なら、治療技術や名前を表示する show() を作ります。
同じ show() という約束を守りながら、中身はクラスごとに違ってよいのです。
インターフェイスはクラスと何が違うのか
インターフェイスは、見た目だけを見るとクラスに似ています。
しかし、性質はかなり違います。
| 比較項目 | クラス | インターフェイス |
|---|---|---|
| 宣言キーワード | class | interface |
| オブジェクト作成 | できる | できない |
| コンストラクタ | 持てる | 持てない |
| フィールド | 通常のフィールドを持てる | 原則として定数になる |
| メソッド | 処理内容を書ける | 原則として宣言だけを書く |
| 主な役割 | 具体的な存在を作る | 共通の約束を作る |
クラスは、具体的なオブジェクトを作るための設計図です。
一方、インターフェイスは、実体そのものを作るというより、クラスが守るべき約束を示します。
鬼滅の刃風にたとえると、WaterSlayer クラスは「水の剣士」という具体的な存在です。
MedicalSlayer クラスは「支援剣士」という具体的な存在です。
それに対して iSlayer インターフェイスは、
「剣士として情報を表示できること」
という能力の約束です。
↓クリックすると拡大表示されます。

インターフェイスのフィールドとメソッドの特徴
インターフェイスでは、メンバに何も修飾子を書かなくても、特別な意味になります。
フィールドは public static final として扱われます。
メソッドは public abstract として扱われます。
| インターフェイスのメンバ | 実際の意味 |
|---|---|
| フィールド | public static final |
| メソッド | public abstract |
そのため、インターフェイスのフィールドは、普通のクラスのようにあとから自由に値を変えるためのものではありません。
基本的には定数として扱われます。
また、メソッドは原則として処理内容を書かず、宣言だけを置きます。
interface iSlayer
{
void show();
}この show() は、次のような意味になります。
| 書いた形 | 意味 |
|---|---|
| void show(); | 実装クラスは show() を必ず定義する |
| 中身がない | 実際の処理は各クラスに任せる |
鬼滅の刃風に言うと、インターフェイスに書くのは「隊の共通任務名」です。
実際にその任務をどう行うかは、水の剣士や支援剣士など、各クラス側で決めます。
インターフェイスはオブジェクトを作成できない
インターフェイスそのものは、new を使ってオブジェクトを作成できません。
たとえば、次のようなインターフェイスがあるとします。
interface iSlayer
{
void show();
}この場合、次のようには書けません。
// これはできない
iSlayer slayer = new iSlayer();インターフェイスは、具体的な処理を持つ完成品ではないからです。
鬼滅の刃風にたとえると、iSlayer は「情報を示せる剣士である」という約束です。
しかし、約束そのものは具体的な人物ではありません。
実際に任務へ出られるのは、WaterSlayer や MedicalSlayer のように、その約束を実装した具体的なクラスです。
ただし、インターフェイスは変数や配列の型として使えます。
| できること | できないこと |
|---|---|
| iSlayer 型の変数を作る | new iSlayer() はできない |
| iSlayer 型の配列を作る | インターフェイス自身の実体は作れない |
| 実装クラスのオブジェクトを代入する | show() の中身なしでは動けない |
この性質が、インターフェイスの大きな特徴です。
↓クリックすると拡大表示されます。

インターフェイスを実装するとはどういうことか
インターフェイスは、クラスと組み合わせて使います。
クラスがインターフェイスの約束を引き受けることを、
インターフェイスを実装する
といいます。
このとき使うのが implements です。
class WaterSlayer implements iSlayer
{
}このように書くと、WaterSlayer クラスは iSlayer インターフェイスを実装していることになります。
鬼滅の刃風にたとえると、WaterSlayer が、
「私は iSlayer の約束を守ります」
と宣言しているようなものです。
そのため、WaterSlayer クラスは iSlayer に書かれている show() を、きちんと定義しなければなりません。
public void show()
{
System.out.println("水の剣士の情報を表示します。");
}つまり、implements は「このクラスは、このインターフェイスの約束を実行できます」と示すための書き方です。
実装したクラスはインターフェイスのメソッドを定義する必要がある
インターフェイスには、メソッドの名前と形だけが書かれています。
たとえば、iSlayer に次のメソッドがあるとします。
void show();iSlayer を実装するクラスでは、この show() の処理内容を定義する必要があります。
| インターフェイス | 実装クラスの責任 |
|---|---|
| show() を持つことを約束する | show() の中身を書く |
| 処理内容は書かない | クラスに合った処理を書く |
| 共通メソッド名を決める | 実際の動きを作る |
鬼滅の刃風にたとえると、iSlayer は「この隊士は情報を示せること」とだけ決めています。
でも、水の剣士が何を表示するか、支援剣士が何を表示するかは、それぞれのクラスで決めます。
このように、インターフェイスは約束を作り、実装クラスがその約束を具体化します。
インターフェイスを実装する
ファイル名:Sample3.java
interface iSlayer
{
void show();
}
class WaterSlayer implements iSlayer
{
private String name;
private String breathingStyle;
public WaterSlayer(String n, String bs)
{
name = n;
breathingStyle = bs;
System.out.println(name + " 水の呼吸「" + breathingStyle + "」の剣士を作成しました。");
}
public void show()
{
System.out.println("水の剣士の名前は" + name + "です。");
System.out.println("呼吸の型は" + breathingStyle + "です。");
}
}
class MedicalSlayer implements iSlayer
{
private String name;
private String healingSkill;
public MedicalSlayer(String n, String hs)
{
name = n;
healingSkill = hs;
System.out.println(name + " 治療技術「" + healingSkill + "」の支援剣士を作成しました。");
}
public void show()
{
System.out.println("支援剣士の名前は" + name + "です。");
System.out.println("治療技術は" + healingSkill + "です。");
}
}
class Sample3
{
public static void main(String[] args)
{
iSlayer[] slayers;
slayers = new iSlayer[2];
slayers[0] = new WaterSlayer("水月", "水流斬り");
slayers[1] = new MedicalSlayer("胡蝶香", "藤花治療");
for(int i = 0; i < slayers.length; i++){
slayers[i].show();
}
}
}実行結果
水月 水の呼吸「水流斬り」の剣士を作成しました。
胡蝶香 治療技術「藤花治療」の支援剣士を作成しました。
水の剣士の名前は水月です。
呼吸の型は水流斬りです。
支援剣士の名前は胡蝶香です。
治療技術は藤花治療です。iSlayer は show() という約束だけを持つ
このプログラムでは、まず iSlayer というインターフェイスを作っています。
interface iSlayer
{
void show();
}ここには show() しか書かれていません。
これは、
iSlayer を実装するクラスは、必ず show() を持つ
という約束です。
ただし、show() の中身はありません。
WaterSlayer と MedicalSlayer が、それぞれ自分の内容に合わせて show() を定義します。
| インターフェイス | 決めていること |
|---|---|
| iSlayer | show() を持つこと |
| WaterSlayer | 水の剣士としての show() を作る |
| MedicalSlayer | 支援剣士としての show() を作る |
つまり、インターフェイスは約束だけを決め、実際の処理はクラスに任せています。
WaterSlayer と MedicalSlayer は implements で約束を引き受けている
WaterSlayer と MedicalSlayer は、どちらも iSlayer を実装しています。
class WaterSlayer implements iSlayer
class MedicalSlayer implements iSlayerimplements iSlayer と書くことで、
このクラスは iSlayer の約束を守ります
と宣言しています。
そのため、どちらのクラスにも show() が定義されています。
| クラス | show() の内容 |
|---|---|
| WaterSlayer | 名前、呼吸の型を表示する |
| MedicalSlayer | 名前、治療技術を表示する |
同じ show() という名前でも、表示する内容は違います。
WaterSlayer の show() では、水の剣士らしい情報を表示しています。
public void show()
{
System.out.println("水の剣士の名前は" + name + "です。");
System.out.println("呼吸の型は" + breathingStyle + "です。");
}MedicalSlayer の show() では、支援剣士らしい情報を表示しています。
public void show()
{
System.out.println("支援剣士の名前は" + name + "です。");
System.out.println("治療技術は" + healingSkill + "です。");
}インターフェイスは、show() という共通の入口だけを決めています。
中身は、それぞれのクラスらしく作れます。
インターフェイス型の配列でまとめて扱える
このプログラムの大きなポイントは、iSlayer[] 型の配列を作っているところです。
iSlayer[] slayers;
slayers = new iSlayer[2];iSlayer はインターフェイスなので、new iSlayer() のように直接オブジェクトは作れません。
しかし、iSlayer 型の配列は作れます。
そして、その配列には iSlayer を実装しているクラスのオブジェクトを入れられます。
slayers[0] = new WaterSlayer("水月", "水流斬り");
slayers[1] = new MedicalSlayer("胡蝶香", "藤花治療");整理すると、次のようになります。
| 配列要素 | 変数としての型 | 実際に入っているオブジェクト |
|---|---|---|
| slayers[0] | iSlayer | WaterSlayer |
| slayers[1] | iSlayer | MedicalSlayer |
そして、ループでは同じように show() を呼び出しています。
for(int i = 0; i < slayers.length; i++){
slayers[i].show();
}呼び出し側は、WaterSlayer なのか MedicalSlayer なのかを細かく気にしていません。
iSlayer を実装しているなら show() を持っている、と分かっているからです。
実際に動く show() は、オブジェクトの実体によって変わります。
| 実体 | 実行される show() |
|---|---|
| WaterSlayer | WaterSlayer の show() |
| MedicalSlayer | MedicalSlayer の show() |
ここにインターフェイスの強さがあります。
クラスの中身が違っていても、共通の約束を持っているなら、同じ型としてまとめて扱えます。
抽象クラスとの共通点と違い
インターフェイスは、抽象クラスと少し似ています。
どちらも、複数のクラスをまとめて扱うために役立ちます。
また、どちらも未完成な要素を持てるため、そのまま直接オブジェクトを作ることはできません。
ただし、役割には違いがあります。
| 比較項目 | 抽象クラス | インターフェイス |
|---|---|---|
| 主な役割 | 共通の土台 | 共通の約束 |
| 通常フィールド | 持てる | 原則として持てない |
| 変更可能な状態 | 持てる | 原則として持たない |
| 通常メソッド | 持てる | 原則として処理を書かない |
| コンストラクタ | 持てる | 持てない |
| 実装の考え方 | extends で継承する | implements で実装する |
鬼滅の刃風にたとえると、抽象クラスは「剣士としての共通の土台」です。
たとえば、speed のような共通状態や setSpeed() のような共通処理を持てます。
一方、インターフェイスは「剣士が守る能力の約束」です。
たとえば、show() を持つこと、fly() を持つこと、support() を持つことのような約束を表します。
| 使い分け | 向いているもの |
|---|---|
| 共通の状態や処理も持たせたい | 抽象クラス |
| 共通のメソッド名や能力だけを約束したい | インターフェイス |
この違いを押さえると、抽象クラスとインターフェイスを混同しにくくなります。
なぜインターフェイスを使うと分かりやすいコードになるのか
インターフェイスを使うと、何を共通ルールとして扱いたいのかがはっきりします。
今回なら、iSlayer を見ただけで、次のことが分かります。
| iSlayer を見て分かること | 内容 |
|---|---|
| show() を持つ | 情報を表示できる |
| 実装クラスが中身を作る | 表示内容はクラスごとに違ってよい |
| iSlayer 型で扱える | 共通の型としてまとめられる |
つまり、iSlayer を実装しているクラスは、必ず show() を使って情報を表示できます。
呼び出す側は、細かいクラス名を意識しなくても、次のように書けます。
slayers[i].show();鬼滅の刃風にたとえると、隊士の見た目や能力は違っていても、iSlayer を実装しているなら、全員が show() で情報を示せるということです。
この共通ルールがあるから、コードがすっきりします。
オブジェクト指向らしい自然な設計につながる
オブジェクト指向では、クラスを「何者か」で整理することもあります。
一方で、「何ができるか」で整理したい場面もあります。
たとえば、WaterSlayer と MedicalSlayer は、まったく違うクラスです。
| クラス | 何者か |
|---|---|
| WaterSlayer | 水の剣士 |
| MedicalSlayer | 支援剣士 |
しかし、どちらも情報を表示できる、という共通点があります。
| クラス | 何ができるか |
|---|---|
| WaterSlayer | show() で情報を表示できる |
| MedicalSlayer | show() で情報を表示できる |
この「何ができるか」を型として表現できるのがインターフェイスです。
つまり、インターフェイスは、
何者かではなく、何ができるかでクラスをまとめるためのしくみ
です。
この考え方が分かると、クラス同士の関係をより柔軟に設計できるようになります。
図:インターフェイスは共通の約束を作る
↓クリックすると拡大表示されます。

この図が示していること
この図では、iSlayer インターフェイスが show() という共通の約束を持っていることを表しています。
上部の iSlayer は、show() の中身までは持っていません。
ただし、iSlayer を実装するクラスは show() を必ず持つ、というルールを決めています。
下部の WaterSlayer と MedicalSlayer は、それぞれ implements iSlayer によって、その約束を引き受けています。
そして、それぞれのクラスに合った show() を実装しています。
| クラス | show() の中身 |
|---|---|
| WaterSlayer | 名前・呼吸の型を表示 |
| MedicalSlayer | 名前・治療技術を表示 |
この図から分かることは、インターフェイスは処理そのものではなく、共通のメソッド名と役割を約束する仕組みだということです。
図:インターフェイス型の配列でまとめて扱う
↓クリックすると拡大表示されます。

この図が示していること
この図では、iSlayer[] 配列に WaterSlayer と MedicalSlayer のオブジェクトを入れて、同じ show() でまとめて扱う流れを表しています。
iSlayer はインターフェイスなので、new iSlayer() のように直接オブジェクトを作ることはできません。
しかし、iSlayer 型の配列や変数として使うことはできます。
配列の中には、iSlayer を実装したクラスのオブジェクトを入れられます。
| 配列要素 | 実体 |
|---|---|
| slayers[0] | WaterSlayer |
| slayers[1] | MedicalSlayer |
ループでは、どちらにも同じように show() を呼び出しています。
slayers[i].show();
それでも、実際に動く show() は実体によって変わります。
| 実体 | 動くメソッド |
|---|---|
| WaterSlayer | WaterSlayer の show() |
| MedicalSlayer | MedicalSlayer の show() |
この図から分かることは、インターフェイスを使うと、違うクラスでも共通の約束をもとに同じ型でまとめて扱えるということです。
鬼滅の刃風にインターフェイスを整理する
インターフェイスは、鬼滅の刃風にたとえると、
剣士が持つ能力や共通ルールの約束
です。
iSlayer を実装しているなら、必ず show() を持ちます。
ただし、show() の中身はクラスごとに違ってよいです。
| クラス | show() の中身 |
|---|---|
| WaterSlayer | 水の剣士として名前と呼吸の型を表示 |
| MedicalSlayer | 支援剣士として名前と治療技術を表示 |
つまり、インターフェイスは次のような考え方です。
| 考え方 | 内容 |
|---|---|
| インターフェイス | 共通の約束を決める |
| implements | クラスが約束を引き受ける |
| 実装クラス | 約束されたメソッドの中身を作る |
| インターフェイス型 | 実装クラスをまとめて扱える |
インターフェイスを使うと、クラスの種類が違っていても、同じ能力や約束を持つものとして扱えます。
この内容で押さえておきたいポイント
| ポイント | 内容 |
|---|---|
| インターフェイス | 共通の約束を定める特別な型 |
| 宣言 | interface を使う |
| 実装 | implements を使う |
| オブジェクト作成 | インターフェイス自身からは直接作れない |
| フィールド | 原則として public static final |
| メソッド | 原則として public abstract |
| 実装クラスの責任 | インターフェイスのメソッドを定義する |
| インターフェイス型配列 | 実装クラスのオブジェクトをまとめて扱える |
| 抽象クラスとの違い | 抽象クラスは共通の土台、インターフェイスは共通の約束 |
インターフェイスは、何者かを表すためのものではなく、何ができるかを表すためのしくみです。
WaterSlayer と MedicalSlayer は別々のクラスです。
しかし、どちらも iSlayer を実装していれば、show() を持つものとして同じ型で扱えます。
この感覚がつかめると、Javaのオブジェクト指向で「共通ルールを作る」意味がかなり見えやすくなります。
