この記事の要点
• interface は「何ができるか」の契約を定義する
• クラスは `implements` で複数のインターフェースを実装できる(多重継承の代替)
• Java 8+ の default メソッド で共通実装を書ける
このシリーズについて
「Java入門」は1本1テーマで進むシリーズです。本記事は第23回として、インターフェース(interface)を扱います。
前提条件: Java入門 #21 - 継承(extends)、Java入門 #22 - ポリモーフィズム を読んでいること。クラス・継承・メソッドオーバーライドの理解が必要です。
インターフェースとは
インターフェース(interface)は、クラスが「何をできるか」を定義する 契約 です。継承(extends)が「is-a 関係」を表すのに対し、インターフェースは 「can-do 関係」 を表します。
| 例 | 継承(is-a) | インターフェース(can-do) |
|---|---|---|
| 犬 | Dog extends Animal → 犬は動物である | Dog implements Runnable → 犬は走ることができる |
| 飛行機 | Airplane extends Vehicle → 飛行機は乗り物である | Airplane implements Flyable → 飛行機は飛ぶことができる |
インターフェースの宣言
インターフェースは interface キーワードで宣言します。
// Flyable.java(Java 21)
public interface Flyable {
void fly(); // 抽象メソッド(実装はなし)
void land(); // セミコロンで終わる
}
インターフェースのメソッドは、デフォルトで public abstract です(public abstract void fly(); と書いても同じ)。
インターフェースの実装
クラスは implements でインターフェースを実装します。実装したメソッドは 必ず全部書かなければなりません。
// Bird.java
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("羽ばたいて飛ぶ");
}
@Override
public void land() {
System.out.println("木の枝に着地");
}
}
// Airplane.java
public class Airplane implements Flyable {
@Override
public void fly() {
System.out.println("エンジンで飛ぶ");
}
@Override
public void land() {
System.out.println("滑走路に着陸");
}
}
// Main.java
public class Main {
public static void main(String[] args) {
Flyable bird = new Bird();
Flyable plane = new Airplane();
bird.fly(); // → 羽ばたいて飛ぶ
plane.fly(); // → エンジンで飛ぶ
}
}
Bird と Airplane は全く異なるクラスですが、同じ Flyable 型 として扱えます(ポリモーフィズム)。
ポイント: インターフェースは「何ができるか」を宣言するだけで、「どうやるか」は各クラスに任せます。これにより柔軟な設計が可能になります。
複数のインターフェースを実装する
Java は クラスの多重継承はできません が、インターフェースは複数実装できます。
// Swimmable.java
public interface Swimmable {
void swim();
}
// Duck.java(飛べて、泳げる)
public class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("低空飛行");
}
@Override
public void land() {
System.out.println("水面に着水");
}
@Override
public void swim() {
System.out.println("水をかいて進む");
}
}
// Main.java
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // Flyable のメソッド
duck.swim(); // Swimmable のメソッド
}
}
Duck は Flyable 型としても Swimmable 型としても扱えます。
Flyable f = new Duck();
Swimmable s = new Duck();
f.fly(); // OK
s.swim(); // OK
インターフェース vs クラス
| 項目 | インターフェース | クラス |
|---|---|---|
| 宣言 | interface Flyable | class Bird |
| メソッド | 抽象メソッド(デフォルト)、default / static メソッド(Java 8+) | 通常のメソッド(実装を持つ) |
| フィールド | public static final のみ(定数) | 通常のフィールド(状態を持てる) |
| コンストラクタ | 持てない | 持てる |
| インスタンス化 | できない(new Flyable() は不可) | できる(new Bird() は可) |
| 多重継承 / 実装 | 複数のインターフェースを implements 可能 | 1つのクラスのみ extends 可能 |
Java 8+ の default メソッド
Java 8 以降では、インターフェースに default メソッド を書けます。これは デフォルトの実装 を持つメソッドで、実装クラスでオーバーライドしなくてもOKです。
// Flyable.java(Java 8+)
public interface Flyable {
void fly();
void land();
// default メソッド(デフォルト実装)
default void takeOff() {
System.out.println("離陸します");
fly();
}
}
// Bird.java
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("羽ばたいて飛ぶ");
}
@Override
public void land() {
System.out.println("木の枝に着地");
}
// takeOff() はオーバーライドしなくてもデフォルト実装が使われる
}
// Main.java
public class Main {
public static void main(String[] args) {
Bird bird = new Bird();
bird.takeOff(); // → 離陸します → 羽ばたいて飛ぶ
}
}
学習のヒント: default メソッドは、後からインターフェースに新しいメソッドを追加しても、既存の実装クラスを壊さないために導入されました(後方互換性)。
static メソッド(Java 8+)
インターフェースには static メソッド も書けます。これはユーティリティメソッドとして使えます。
public interface Flyable {
void fly();
// static メソッド
static void printWarning() {
System.out.println("飛行中は座席ベルトを着用してください");
}
}
// 呼び出し
Flyable.printWarning(); // インターフェース名.メソッド名
インターフェースの構成要素まとめ
| 要素 | 修飾子 | 実装 | Java バージョン |
|---|---|---|---|
| 抽象メソッド | public abstract(暗黙) | なし(実装クラスが書く) | Java 1.0~ |
| default メソッド | public default | あり(実装クラスでオーバーライド可) | Java 8~ |
| static メソッド | public static | あり(インターフェース名で呼ぶ) | Java 8~ |
| 定数フィールド | public static final(暗黙) | 初期値が必須 | Java 1.0~ |
実践例: 複数のインターフェースでロールを表現
// Printable.java
public interface Printable {
void print();
}
// Saveable.java
public interface Saveable {
void save();
}
// Document.java(印刷でき、保存もできる)
public class Document implements Printable, Saveable {
private String content;
public Document(String content) {
this.content = content;
}
@Override
public void print() {
System.out.println("印刷: " + content);
}
@Override
public void save() {
System.out.println("保存: " + content);
}
}
// Main.java
public class Main {
public static void main(String[] args) {
Document doc = new Document("重要な契約書");
doc.print(); // → 印刷: 重要な契約書
doc.save(); // → 保存: 重要な契約書
}
}
まとめ
| 概念 | 説明 |
|---|---|
| interface | 「何ができるか」を定義する契約 |
| implements | クラスがインターフェースを実装する宣言 |
| 複数実装 | implements A, B, C で複数のインターフェースを実装可能 |
| 抽象メソッド | 実装を持たないメソッド(実装クラスが必ず書く) |
| default メソッド(Java 8+) | デフォルト実装を持つメソッド(オーバーライド任意) |
| static メソッド(Java 8+) | インターフェース名で呼ぶユーティリティメソッド |
次のステップ
Java入門 #24 - 抽象クラス(abstract class) で、インターフェースと通常のクラスの中間的な存在を学びます。
参考リソース
- Defining an Interface(Oracle Java Tutorial) — インターフェースの公式ガイド
- Default Methods(Oracle) — default メソッドの詳細
- Java SE 21 ドキュメント