インタフェース (抽象型)

インタフェース () は、主にオブジェクト指向プログラミングにおいて用いられる抽象型の一種であり、クラスやオブジェクトが提供すべき操作の仕様のみを定め、具体的な実装を含まない型である。多くの言語ではクラスが複数のインタフェースを実装できるため、異なる実装を持つオブジェクトを共通の型として扱うことが可能となり、部品の交換や再利用を容易にし、多態性に基づく柔軟なソフトウェア設計を実現する。

 概要 
オブジェクト指向プログラミングにおいて、多重継承はプログラミングの自由度と柔軟性を向上する。C++は「実装の多重継承」をサポートし、クラスは複数のスーパークラス（基底クラス）を持つことができる。しかし、実装の多重継承は菱形継承問題などの欠点を抱えている。実装の多重継承の問題点を回避するためにC++は仮想継承の仕組みを導入したが、これはプログラミング言語仕様が複雑化する原因となった。しかし、「型の多重継承」に限れば、問題点の多くは回避でき、また言語仕様もシンプルになる。JavaおよびC#では、実装の継承は単一継承に制限したうえで、代わりに具体的な実装を持たないインタフェースによる型の多重継承の仕組みを導入し、多重継承問題に対する解決策を提供している。

インタフェース自身はインスタンス化（実体化）することができないが、任意のクラスにてインタフェースを実装することで、そのクラスのインスタンスは当該インタフェースとして振る舞うことが可能となる（リスコフの置換原則）。

JavaおよびC#では、抽象メソッド（実装を持たないメソッド宣言）を持ち、実体化できないクラス（抽象クラス）を定義することも可能であるが、抽象クラスは実装を持つことも可能であり、インタフェースと違って多重継承することはできない。

インタフェース型に含めることのできる構文要素は、具体的な実装を持たない抽象メンバーの宣言のみが基本であるが、後述のように詳細は言語ごとに異なる。利便性の観点から、言語仕様の改訂（バージョンアップ）により制限が部分的に緩和され、静的メンバーの実装など、インタフェースに定義可能な要素が増えるケースもある。

 Java 
Javaのインタフェースは、暗黙的な抽象メソッドのみを持つことが許される参照型である。定数および入れ子になった型の定義は許される。メンバーのアクセスレベルはデフォルトでとなる。Javaではクラスの継承にキーワードを使用するが、インタフェースの実装にはキーワードを使用する。インタフェースを拡張して新たなインタフェースを派生させるときはキーワードを使う。
// 「飛ぶ」ことができるもの全般を表すインタフェース。
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();
        }
    }
}
上記では、互いに異なる基底クラスを持つ派生クラス群であっても、Flyableインタフェースを導入することで一様に扱うことができる例を示している。

Javaの列挙型は抽象クラスから暗黙的に派生する参照型であり、任意のインタフェースを実装することができる。

なお、Java 8以降ではインタフェースのデフォルトメソッドにより、実装の多重継承も限定的にサポートするようになった。また、インタフェースが静的メソッドを持つこともできるようになったDefault Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)。Java 8で導入されたラムダ式およびメソッド参照は、実装すべきメソッドをひとつだけ持つ「関数型インタフェース」(functional interface) によって実現されている。

 C# 
C#のインタフェースinterface キーワード - C# reference | Microsoft Learnは、概ねJava同様であり、暗黙的な抽象メソッド、抽象プロパティインターフェイスのプロパティ - C# | Microsoft Learn、抽象インデクサインターフェイスのインデクサー - C# | Microsoft Learn、抽象イベントインターフェイス イベントを実装する方法 - C# | Microsoft Learnのみを持つことが許される参照型である。メンバーのアクセスレベルはデフォルトでとなるアクセス修飾子 - C# | Microsoft Learn。C# 7.xまでは、定数、入れ子になった型、静的フィールドや静的メソッドなどの定義は許されなかったが、C# 8.0以降では定義できるようになったDefault interface methods - C# feature specifications | Microsoft Learn。また、C# 8.0ではメンバーのデフォルト実装を定義することもできるようになったC# の歴史 / §C# バージョン 8.0 | Microsoft Learn。インタフェース名はIで始めることが推奨されているクラス、構造体、およびインターフェイスの名前 - Framework Design Guidelines | Microsoft Docs。言語の機能や設計の観点から言うと、C#のインタフェースにはDelphi (Object Pascal) のインタフェースの影響が強く見られる。

interface IMyInterface
{
    // メソッド宣言。
    void SomeMethod();
    // プロパティ宣言。型、名前、読み書きの方向を宣言する。
    double SomeProperty { get; set; }
    // インデクサ宣言。
    string this[int index] { get; set; }
    // イベント宣言。
    event System.EventHandler SomethingChanged;
}
インタフェースのプロパティはC# 3.0以降の自動実装プロパティと類似の構文だが、インタフェースは状態を持たないため、プロパティ抽象プロパティを定義する方法 - C# | Microsoft Learn同様にバッキングフィールドは生成されない。

C#の構造体は抽象クラスSystem.ValueTypeから暗黙的に派生する値型であり、基底クラスを明示的に指定することはできないが、任意のインタフェースを実装することはできる構造体型 - C# リファレンス | Microsoft Docs。C#の列挙型は抽象クラスSystem.Enumから暗黙的に派生する値型であるが、構造体とは違って任意のインタフェースを実装することはできない。構造体および列挙型のインスタンスは、実装されたインタフェース型の変数に暗黙的に代入できるが、型変換（キャスト）の際にボックス化が発生する。

usingステートメントで使用できるSystem.IDisposableのように、構文上特別扱いされるようになるインタフェース型もあるIDisposable Interface (System) | Microsoft Docs。

また、C#ではGuid属性（System.Runtime.InteropServices.GuidAttributeクラス）により、インタフェースやクラスにGUIDを付加することができる。.NET Frameworkのインタフェースやクラスを含むアセンブリをCOMコンポーネントとして公開し、C++ネイティブコードやVBScript/JScriptといった従来のCOM/OLE対応言語などから利用するCOM相互運用も可能であるCOM への .NET Framework コンポーネントの公開 | Microsoft Docs。

 VB.NET 
C#の姉妹言語であるVisual Basic .NET (VB.NET) もインタフェースをサポートし、抽象メンバーのみを持つ参照型である点は同じだが、入れ子になった型は定義できるものの、定数や静的メンバー（共有メンバー）などの定義は許されないインターフェイス - Visual Basic | Microsoft Docs。

 Delphi 
Delphi (Object Pascal) のインタフェースは、暗黙的にpublicな抽象メソッドと抽象プロパティのみを持つことが許される参照型であるオブジェクト インターフェイス（Delphi） - RAD Studio。インタフェース型は、基本インタフェースIInterfaceまたは他のインタフェースから派生する。

C#の設計者アンダース・ヘルスバーグは、マイクロソフトに移籍する前はボーランドにてDelphiの開発に従事していた。特に初期のC#の言語機能はDelphiの影響を強く受けており世界のプログラミング言語(22) 今も改良が続くPascal/Delphi言語の栄枯盛衰 | TECH+、インタフェースに関しても例外ではない。

 UML 
統一モデリング言語 (UML) におけるインタフェースは、クラスまたはコンポーネントなどの他のモデル要素が実装しなければならない、操作 (operation) の集合を定義するモデル要素である。ある実装モデル要素は、あるインタフェースが宣言する各操作をオーバーライドすることで、そのインタフェースを実現するInterfaces - IBM Documentation。UMLのクラス図では、«interface»のキーワードを含むクラスの矩形シンボルによって表現される。

 その他の言語・技術 
C++ではpublicな純粋仮想関数および純粋仮想デストラクタのみを持つクラス（あるいは構造体）を定義することで、JavaやC#のインタフェースを模倣し、多重継承の欠点を回避することもできる。

マイクロソフトのComponent Object Model (COM) は、プログラミング言語を問わず再利用可能なソフトウェアコンポーネントを作成するために用いられる技術であり、COMインタフェースはIUnknown派生の実装を持たない抽象型として、COMサーバーとCOMクライアントをつなぐ役割を果たす。COMの思想や概念はのちに.NET FrameworkやWindowsランタイムにも受け継がれることになった。

 脚注 

 注釈 

 出典 

 関連項目 
 抽象型
 クラス (コンピュータ)
 継承 (プログラミング)
 インタフェース (情報技術)

Category:データ型
Category:抽象
Category:プログラミング言語の構文