インタフェース (抽象型)インタフェース (英: interface) は、JavaやC#などのオブジェクト指向プログラミング言語においてサポートされる、実装を持たない抽象型のことである。これらの言語において、クラスは実装の多重継承をサポートしない代わりに、任意の数のインタフェースを実装 (implement) することができ、これにより型の多重継承をサポートする。複数の種類のオブジェクトを、インタフェースを用いた多態性によって統一的に扱うことができるようになる。インターフェイスやインターフェースなどと表記することもある[注釈 1]。 概要オブジェクト指向プログラミングにおいて、多重継承はプログラミングの自由度と柔軟性を向上する。C++は「実装の多重継承」をサポートし、クラスは複数のスーパークラス(基底クラス)を持つことができる。しかし、実装の多重継承は菱形継承問題などの欠点を抱えている。実装の多重継承の問題点を回避するためにC++は仮想継承の仕組みを導入したが、これはプログラミング言語仕様が複雑化する原因となった。しかし、「型の多重継承」に限れば、問題点の多くは回避でき、また言語仕様もシンプルになる。JavaおよびC#では、実装の継承は単一継承に制限したうえで、代わりに具体的な実装を持たないインタフェースによる型の多重継承の仕組みを導入し、多重継承問題に対する解決策を提供している[1]。 インタフェース自身はインスタンス化(実体化)することができないが、任意のクラスにてインタフェースを実装することで、そのクラスのインスタンスは当該インタフェースとして振る舞うことが可能となる(リスコフの置換原則)。 JavaおよびC#では、抽象メソッド(実装を持たないメソッド宣言)を持ち、実体化できないクラス(抽象クラス)を定義することも可能であるが、抽象クラスは実装を持つことも可能であり、インタフェースと違って多重継承することはできない。 インタフェース型に含めることのできる構文要素は、具体的な実装を持たない抽象メンバーの宣言のみが基本であるが、後述のように詳細は言語ごとに異なる。利便性の観点から、言語仕様の改訂(バージョンアップ)により制限が部分的に緩和され、静的メンバーの実装など、インタフェースに定義可能な要素が増えるケースもある。 JavaJavaのインタフェースは、暗黙的な抽象メソッドのみを持つことが許される参照型である。定数および入れ子になった型の定義は許される。メンバーのアクセスレベルはデフォルトで // 「飛ぶ」ことができるもの全般を表すインタフェース。
interface Flyable {
void fly();
}
// 動物の抽象基底クラス。
abstract class Animal {
}
// 鳥類の抽象基底クラス。空を飛べないダチョウやペンギンも含まれる。
abstract class Bird extends Animal {
}
// 飛べる鳥類の抽象基底クラス。
abstract class FlyingBird extends Bird implements Flyable {
}
// ワシの具象クラス。
class Eagle extends FlyingBird {
@Override
public void fly() { System.out.println("Eagle.fly()"); }
}
// 哺乳類の抽象基底クラス。
abstract class Mammal extends Animal {
}
// 飛べる哺乳類の抽象基底クラス。
abstract class FlyingMammal extends Mammal implements Flyable {
}
// コウモリの具象クラス。
class Bat extends FlyingMammal {
@Override
public void fly() { System.out.println("Bat.fly()"); }
}
// 航空機の抽象基底クラス。自力で航行できないグライダーも含まれる。
abstract class Aircraft {
}
// エンジンを搭載した飛行機の具象クラス。
class Airplane extends Aircraft implements Flyable {
@Override
public void fly() { System.out.println("Airplane.fly()"); }
}
public class Main {
public static void main(String[] args) {
final Flyable[] flyables = {
new Eagle(),
new Bat(),
new Airplane(),
};
for (final Flyable obj : flyables) {
obj.fly();
}
}
}
上記では、互いに異なる基底クラスを持つ派生クラス群であっても、 Javaの列挙型は抽象クラス なお、Java 8以降ではインタフェースのデフォルトメソッドにより、実装の多重継承も限定的にサポートするようになった。また、インタフェースが静的メソッドを持つこともできるようになった[2]。Java 8で導入されたラムダ式およびメソッド参照は、実装すべきメソッドをひとつだけ持つ「関数型インタフェース」(functional interface) によって実現されている。 C#C#のインタフェース[3]は、概ねJava同様であり、暗黙的な抽象メソッド、抽象プロパティ[4]、抽象インデクサ[5]、抽象イベント[6]のみを持つことが許される参照型である。メンバーのアクセスレベルはデフォルトで interface IMyInterface
{
// メソッド宣言。
void SomeMethod();
// プロパティ宣言。型、名前、読み書きの方向を宣言する。
double SomeProperty { get; set; }
// インデクサ宣言。
string this[int index] { get; set; }
// イベント宣言。
event System.EventHandler SomethingChanged;
}
インタフェースのプロパティはC# 3.0以降の自動実装プロパティと類似の構文だが、インタフェースは状態を持たないため、 C#の構造体は抽象クラス usingステートメントで使用できる また、C#では VB.NETC#の姉妹言語であるVisual Basic .NET (VB.NET) もインタフェースをサポートし、抽象メンバーのみを持つ参照型である点は同じだが、入れ子になった型は定義できるものの、定数や静的メンバー(共有メンバー)などの定義は許されない[15]。 DelphiDelphi (Object Pascal) のインタフェースは、暗黙的にpublicな抽象メソッドと抽象プロパティのみを持つことが許される参照型である[16]。インタフェース型は、基本インタフェース C#の設計者アンダース・ヘルスバーグは、マイクロソフトに移籍する前はボーランドにてDelphiの開発に従事していた。特に初期のC#の言語機能はDelphiの影響を強く受けており[17]、インタフェースに関しても例外ではない。 UML統一モデリング言語 (UML) におけるインタフェースは、クラスまたはコンポーネントなどの他のモデル要素が実装しなければならない、操作 (operation) の集合を定義するモデル要素である。ある実装モデル要素は、あるインタフェースが宣言する各操作をオーバーライドすることで、そのインタフェースを実現する[18]。UMLのクラス図では、«interface»のキーワードを含むクラスの矩形シンボルによって表現される。 その他の言語・技術C++ではpublicな純粋仮想関数および純粋仮想デストラクタのみを持つクラス(あるいは構造体)を定義することで、JavaやC#のインタフェースを模倣し、多重継承の欠点を回避することもできる。 マイクロソフトのComponent Object Model (COM) は、プログラミング言語を問わず再利用可能なソフトウェアコンポーネントを作成するために用いられる技術であり、COMインタフェースはIUnknown派生の実装を持たない抽象型として、COMサーバーとCOMクライアントをつなぐ役割を果たす。COMの思想や概念はのちに.NET FrameworkやWindowsランタイムにも受け継がれることになった。 脚注注釈出典
関連項目 |