Javaインターフェース完全ガイド: 定義・実装・多重継承・タグインターフェース
インターフェースはJavaの参照型です。クラスに似ています。抽象メソッドのコレクションです。クラスがインターフェースを実装すると、そのインターフェースの抽象メソッドを継承します。
抽象メソッドに加えて、インターフェースには定数、デフォルトメソッド、静的メソッド、ネスト型を含めることもできます。メソッドボディが存在するのはデフォルトメソッドと静的メソッドのみです。
インターフェースの記述はクラスの記述に似ています。しかしクラスはオブジェクトの属性と振る舞いを記述します。一方インターフェースは、クラスが実装する振る舞いを含みます。
そのインターフェースを実装するクラスが抽象でない限り、インターフェースのすべてのメソッドをクラスで定義する必要があります。
インターフェースとクラスの共通点
- インターフェースには任意の数のメソッドを含められる。
- インターフェースは
.java拡張子のファイルに記述され、インターフェース名がファイル名と一致する。 - インターフェースのバイトコードは
.classファイルに現れる。 - インターフェースはパッケージに属し、対応するバイトコードファイルはパッケージ名と一致するディレクトリ構造に配置される。
インターフェースとクラスの相違点
- インターフェースをインスタンス化できない。
- インターフェースにはコンストラクタがない。
- インターフェースのすべてのメソッドは抽象的である(暗黙的に)。
- インターフェースにはインスタンスフィールドを含められない。インターフェースに現れるフィールドは
staticかつfinalで宣言しなければならない。 - インターフェースはクラスによって拡張されない。クラスによって実装される。
- インターフェースは複数のインターフェースを拡張できる。
インターフェースの宣言
interfaceキーワードを使用してインターフェースを宣言します。シンプルな例を示します。
例
/* File name : NameOfInterface.java */
import java.lang.*; // 任意の数のimport文
public interface NameOfInterface {
// 任意の数のfinal、staticフィールド
// 任意の数の抽象メソッド宣言
}
インターフェースには以下のプロパティがあります。
- インターフェースは暗黙的にabstractです。インターフェース宣言時に
abstractキーワードを使用する必要はありません。 - インターフェースの各メソッドも暗黙的にabstractなので、
abstractキーワードは不要です。 - インターフェースのメソッドは暗黙的に
publicです。
例: Animalインターフェース
/* File name : Animal.java */
interface Animal {
public void eat();
public void travel();
}
インターフェースの実装
クラスがインターフェースを実装すると、そのクラスはインターフェースの特定の振る舞いを実行する契約を結んだと考えられます。クラスがインターフェースのすべての振る舞いを実行しない場合、そのクラスはabstractと宣言しなければなりません。
クラスはimplementsキーワードを使用してインターフェースを実装します。implementsキーワードはクラス宣言のextends部分の後に現れます。
例: MammalIntクラスでAnimalを実装
/* File name : MammalInt.java */
public class MammalInt implements Animal {
public void eat() {
System.out.println("Mammal eats");
}
public void travel() {
System.out.println("Mammal travels");
}
public int noOfLegs() {
return 0;
}
public static void main(String args[]) {
MammalInt m = new MammalInt();
m.eat();
m.travel();
}
}
出力
Mammal eats
Mammal travels
インターフェースで定義されたメソッドをオーバーライドする際にはいくつかのルールがあります。
- インターフェースメソッドまたはそのサブクラスで宣言されているもの以外のチェック例外を実装メソッドで宣言してはならない。
- インターフェースメソッドのシグニチャと同じ戻り値の型またはサブタイプを維持しなければならない。
- 実装クラス自体をabstractにできる。その場合、インターフェースメソッドを実装する必要はない。
インターフェースを実装する際のいくつかのルール:
- クラスは同時に複数のインターフェースを実装できる。
- クラスは1つのクラスのみ拡張できるが、多くのインターフェースを実装できる。
- インターフェースは、クラスが別のクラスを拡張するのと同様に、別のインターフェースを拡張できる。
インターフェースの拡張
インターフェースは、クラスが別のクラスを拡張するのと同じように、別のインターフェースを拡張できます。extendsキーワードを使用してインターフェースを拡張し、子インターフェースは親インターフェースのメソッドを継承します。
以下のSportsインターフェースはHockeyとFootballインターフェースによって拡張されます。
例
// Filename: Sports.java
public interface Sports {
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
// Filename: Football.java
public interface Football extends Sports {
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
// Filename: Hockey.java
public interface Hockey extends Sports {
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
Hockeyインターフェースには4つのメソッドがありますが、Sportsから2つを継承しています。したがってHockeyを実装するクラスはすべての6つのメソッドを実装する必要があります。同様にFootballを実装するクラスはFootballの3つのメソッドとSportsの2つのメソッドを定義する必要があります。
複数インターフェースの拡張
Javaクラスは1つの親クラスのみ拡張できます。多重継承は許可されていません。しかしインターフェースはクラスではないため、インターフェースは複数の親インターフェースを拡張できます。
extendsキーワードは1回使用し、親インターフェースをカンマ区切りで宣言します。
例えばHockeyインターフェースがSportsとEventの両方を拡張する場合、以下のように宣言されます。
例
public interface Hockey extends Sports, Event
タグインターフェース
インターフェースの拡張の最も一般的な用途は、親インターフェースにメソッドが含まれていない場合です。例えば、java.awt.eventパッケージのMouseListenerインターフェースはjava.util.EventListenerを拡張しており、これは以下のように定義されています。
例
package java.util;
public interface EventListener {}
メソッドを持たないインターフェースをタグインターフェースと呼びます。タグインターフェースには2つの基本的な設計目的があります。
共通の親を作成 - EventListenerインターフェースのように、Java APIで数十の他のインターフェースによって拡張される場合、タグインターフェースを使用してインターフェースグループの共通の親を作成できます。例えば、インターフェースがEventListenerを拡張すると、JVMはこの特定のインターフェースがイベント委譲シナリオで使用されることを知ります。
クラスにデータ型を追加 - ここから「タグ」という用語が来ています。タグインターフェースを実装するクラスはメソッドを定義する必要がありません(インターフェースにメソッドがないため)が、ポリモーフィズムを通じてそのクラスはインターフェース型になります。
Java
- Javaのfinalキーワード完全解説:変数、メソッド、クラスでの活用法
- Java instanceof演算子完全ガイド:基本から継承・インターフェースまで
- Javaインターフェース完全ガイド:概念、実装、ベストプラクティス
- Java Staticネストクラスの理解:用法、違い、実例
- Java無名インナークラス完全ガイド:定義、構文、実践例
- Javaシングルトンパターン完全解説:安全な実装と活用法
- Javaリフレクション完全ガイド:実行時のクラス・メソッド・フィールド検査
- Java ObjectOutputStream完全ガイド:シリアル化、メソッド、実践例
- Javaジェネリクス完全ガイド:再利用可能で型安全なコードの構築
- Javaファイル操作のマスター:java.ioによる作成・読み取り・書き込み・削除
- Java インターフェース vs 抽象クラス:適切な抽象化の選び方