English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# インターフェース(Interface)

人間の世界では、2人以上の人々の間の契約は、契約に従うことを約束します。同様に、インターフェースには関連する機能の宣言が含まれています。インターフェースを実装する実体は、宣言された機能の実装を提供する必要があります。

C# では、interface キーワードを使用してインターフェースを定義できます。インターフェースには、メソッド、プロパティ、インデクサーやイベントの宣言が含まれますが、フィールドや自動実装のプロパティは含まれません。

以下のインターフェースはファイル操作の基本的な機能を宣言しています。

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}

アクセス修飾子はインターフェースメンバーに適用できません。デフォルトでは、すべてのメンバーがパブリックです。インターフェースでアクセス修飾子を使用すると、C# コンパイラは「修飾子 'public'」というコンパイル時エラーを出力します。/private/protected' はこのアイテムに対して有効ではありません。(Visual Studio は即座にエラーを表示し、コンパイルを行いません。)

interface IFile
{
    protected void ReadFile(); //コンパイル時エラー
    private void WriteFile(string text);//コンパイル時エラー
}

インターフェースは宣言のみを含むことができ、実装を含むことはできません。以下はコンパイル時エラーを引き起こします。

interface IFile
{
    void ReadFile();
    void WriteFile(string text){
        Console.Write(text);  //エラー:メソッドの実装ができません
    }
}

インターフェースの実装

クラスまたはStructは、コロン(:)を使用して1つまたは複数のインターフェースを実装できます。  

構文:

<Class or Struct Name> : <Interface Name>

例えば、以下のクラスはIFileインターフェースを暗黙的に実装しています。

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
class FileInfo : IFile
{
    public void ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    public void WriteFile(string text)
    {
        Console.WriteLine("ファイルに書き込み中");
    }
}

上記の例では、FileInfoクラスがIFileインターフェースを実装しています。それによりpublicアクセス修飾子でIFileインターフェースのすべてのメンバーを定義しています。FileInfoクラスはインターフェースメンバー以外のメンバーも含むことができます。

インターフェースメンバーはpublic修飾子で実装する必要があります;そうしないとコンパイラがコンパイル時エラーを出します。

以下のように、このクラスのオブジェクトを作成し、インターフェースの変数に割り当てることができます。

public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        FileInfo file2 = new FileInfo();
        file1.ReadFile(); 
        file1.WriteFile("content"); 
        file2.ReadFile(); 
        file2.WriteFile("content"); 
    }
}

上記では、FileInfoクラスのオブジェクトを作成し、それをIFile型の変数とFileInfo型の変数に割り当てました。インターフェースが暗黙的に実装されている場合、IFile型の変数およびFileInfo型の変数を使用してIFileメンバーにアクセスできます。

明示的な実装

インターフェースは<InterfaceName>.<MemberName>を使用して明示的に実装できます。クラスが複数のインターフェースを実装している場合、明示的な実装は便利です;したがって、読みやすく混乱を避けることができます。インターフェースに同じメソッド名がある場合も便利です。

以下を public 修飾子は明示的な実装と一緒に使用されます。それによりコンパイル時エラーが発生します。
interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
    
class FileInfo : IFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    void IFile.WriteFile(string text)
    {
        Console.WriteLine("ファイルに書き込み中");
    }
}

インターフェースを実装する際には、インターフェースのインスタンスのみを通じてインターフェースのメンバーにアクセスできます。

interface IFile
{
    void ReadFile();
    void WriteFile(string text);
}
class FileInfo : IFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("Reading File")
    }
    void IFile.WriteFile(string text)
    {
        Console.WriteLine("ファイルに書き込み中");
    }
    public void Search(string text)
    {
        Console.WriteLine("ファイル内で検索中");
    }
}
public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        FileInfo file2 = new FileInfo();
        file1.ReadFile(); 
        file1.WriteFile("content"); 
        //file1.Search("検索するテキスト")//コンパイル時エラー 
        
        file2.Search("検索するテキスト");
        //file2.ReadFile(); //コンパイル時エラー 
        //file2.WriteFile("content"); //コンパイル時エラー 
    }
}

上記の例では、file1オブジェクトがアクセスできるメンバーIFile、およびfile2FileInfoクラスのメンバーにアクセスできます。これは明示的な実装の限界です。

複数のインターフェースの実装

クラスや構造体は複数のインターフェースを実装できます。すべてのインターフェースのすべてのメンバーを実装する必要があります。

interface IFile
{
    void ReadFile();
}
interface IBinaryFile
{
    void OpenBinaryFile();
    void ReadFile();
}
class FileInfo : IFile, IBinaryFile
{
    void IFile.ReadFile()
    {
        Console.WriteLine("テキストファイルを読み取り中");
    }
    void IBinaryFile.OpenBinaryFile()
    {
        Console.WriteLine("バイナリファイルをオープン中");
    }
    void IBinaryFile.ReadFile()
    {
        Console.WriteLine("バイナリファイルを読み取り中");
    }
    public void Search(string text)
    {
        Console.WriteLine("ファイル内で検索中");
    }
}
public class Program
{
    public static void Main()
    {
        IFile file1 = new FileInfo();
        IBinaryFile file2 = new FileInfo();
        FileInfo file3 = new FileInfo();
        file1.ReadFile(); 
        //file1.OpenBinaryFile(); //コンパイル時エラー 
        //file1.SearchFile("検索するテキスト"); //コンパイル時エラー 
        
        file2.OpenBinaryFile();
        file2.ReadFile();
        //file2.SearchFile("検索するテキスト"); //コンパイル時エラー 
    
        file3.Search("検索するテキスト");
        //file3.ReadFile(); //コンパイル時エラー 
        //file3.OpenBinaryFile(); //コンパイル時エラー 
    }
}

上記、FileInfoはIFileおよびIBinaryFileの2つのインターフェースを明示的に実装しています。インターフェースを複数実装する場合、明示的に実装することで混乱を避け、可読性を向上させることを推奨します。

覚えておくべきポイント:
  1. インターフェースにはメソッド、属性、インデックス、イベントの宣言を含むことができます。

  2. インターフェースにはプライベートメンバー、プロテクテッドメンバー、内部メンバーを含むことができません。デフォルトでは、すべてのメンバーが公開されます。

  3. インターフェースにはフィールドや自動実装の属性を含むことができません。

  4. クラスや構造体は、インターフェースを実装する際に、public修飾子を使用して暗黙的な実装を行います。明示的な実装の場合は、それを使用しないでください。

  5. インターフェースを実装するには、InterfaceName. MemberName を明示的に使用します。

  6. 一つのインターフェースは、一つまたは複数のインターフェースを継承できます。