インタフェース
この節の要点
- 実装を一切持たない抽象クラスをインターフェースと呼ぶ。
- Javaでは複数の概念を親として継承させたいとき、各概念をインタフェースとして定義することで多重継承することができる。
ある概念の上位の概念は独立して複数存在することが一般的です。
例えば、「イルカ」の上位概念は、「哺乳類」や「海洋生物」などが、「高専寮生」の上位概念は、「寮生」や「高専生」などがあります。
複数の概念を継承することを多重継承(multiple inheritance) と呼びます。多重継承は、パフォーマンスの問題やひし形継承問題を引き起こします。これら問題を避けるために、Javaでは継承の仕組みにおいて複数の概念(スーパークラス)を元に下位の概念(サブクラス)を作ることはできません。しかしながら、インターフェース(Interface) と呼ばれる抽象クラス構造を使うことで、(インターフェース間の)多重継承を実現できます。
インターフェースは 抽象メソッドのみ からなる純粋な抽象クラス構造です。すなわち、純化した抽象概念と見なすことができます。つまり抽象クラスと同様に、インターフェース自身からオブジェクトを作成することはできません。また、インターフェースは抽象クラスとは異なり、インスタンスフィールドや具体的な振る舞い(実装)を含めることはできません。
インターフェースを駆使することで、オブジェクト指向プログラミングにおいて再利用性および保守性を高めつつ階層化したプログラムを作成することができます。
インターフェースを元に新たにクラスを作成することを実装(Implementation) と呼びます。図32、図33、図34にインターフェースの実装例を示します。
/**
* 高専生です。
*/
public interface KosenStudent {
/**
* IDを取得します。
* @return IDです。
*/
public String getID();
}
/**
* 寮生です。
*/
public interface Ryousei {
/**
* 在寮しているか判定します。
* @param date 日付です。
* @return 材料していればtrue、していなければfalse。
*/
public boolean isStayed(DateTime date);
}
/**
* R02年度の津山高専寮生です。
*/
public class TsuyamaR02 implements Ryousei, KosenStudent {
/**
* 名前と番号を設定します。
* @param name 名前です。
* @param num 番号です。
*/
public TsuyamaR02(String name, int num) {
/* 中略 */
}
@Override
public boolean isStayed(DateTime date) {
/* 中略 */
}
@Override
public String getID() {
/* 中略 */
}
}
図34における、実装の指定を抽出すると図35になります。Javaではimplementsキーワードを使うことで実装インタフェースを指定できます。
public class TsuyamaR02 implements Ryousei, KosenStudent {
インターフェースにおいては、abstract修飾子を記述する必要はなく、定義されたメソッドは全てabstractになります。また、インタフェースの実装クラスはそのインタフェース型に代入互換性があります。つまり、クラスの継承関係と同様に、インタフェースを実装したクラスオブジェクトは、その実装したインタフェース型の変数に代入することができます。従って、同様に多態性を実現することができます。
インタフェースをクラス図で表す際は、図35のように、名称の上部に<<interface>>を付ける必要があります。また実装関係を表すために、白抜き三角矢印の破線を使います。
