C#のインターフェースは、オブジェクト指向プログラミングにおいて非常に重要な役割を果たします。クラスの枠を越えた共通の契約を定義し、柔軟で拡張性のあるコードを書くために不可欠な概念です。しかし、初心者にとっては「インターフェースって何?」「抽象クラスとどう違うの?」という疑問が浮かぶこともあるでしょう。この記事では、C#のインターフェースの基礎から、実践的な活用方法までをわかりやすく解説します。オブジェクト指向の理解を深め、よりスマートなC#コードを書けるようになりましょう。
インターフェースとは「クラスや構造体が実装すべきメソッドやプロパティの定義だけを記述した型」です。C#ではinterface
キーワードを使って定義します。
public interface IAnimal
{
void Speak();
string Name { get; set; }
}
このように、インターフェースには処理の中身を記述せず、メソッドやプロパティのシグネチャだけを書きます。
インターフェースを実装するには、:
記号を使ってクラスに紐づけます。
public class Dog : IAnimal
{
public string Name { get; set; }
public void Speak()
{
Console.WriteLine("ワン!");
}
}
public interface IWalker
{
void Walk();
}
public class Human : IAnimal, IWalker
{
public string Name { get; set; }
public void Speak() => Console.WriteLine("こんにちは!");
public void Walk() => Console.WriteLine("歩いています。");
}
インターフェースを使うことで、異なるクラスでも同じ操作ができるようになります。たとえば、IAnimal
を実装したDog
もCat
も、Speak()
メソッドを持っているため、共通の処理で扱うことが可能です。
void Introduce(IAnimal animal)
{
Console.WriteLine($"こんにちは、{animal.Name}です。");
animal.Speak();
}
インターフェースを使えば、モックオブジェクトを用いてテストが簡単になります。実装に依存せず、抽象的な操作に対してテストできるため、単体テストやDI(依存性注入)と相性が良いです。
クラスの多重継承はできませんが、インターフェースなら複数実装が可能です。複数の機能を小さく分け、それらを必要に応じて組み合わせることで、再利用性の高い設計ができます。
C#には「抽象クラス(abstract class)」という似た仕組みがありますが、インターフェースとは用途が異なります。
項目 | インターフェース | 抽象クラス |
---|---|---|
実装の有無 | 実装を持たない(C#8以降一部可能) | 一部または全部実装可能 |
継承数 | 複数実装可能 | 単一継承のみ |
コンストラクタ | なし | あり |
フィールド | 不可 | 可 |
以下は、複数のクラスでインターフェースを共通に使い、処理を統一する例です。
public interface ILogger
{
void Log(string message);
}
public class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine($"[Console] {message}");
}
}
public class FileLogger : ILogger
{
public void Log(string message)
{
System.IO.File.AppendAllText("log.txt", $"{message}\n");
}
}
// 呼び出し側
void WriteLog(ILogger logger)
{
logger.Log("エラーが発生しました。");
}
このように、呼び出し側はILogger
という「契約」だけを意識すればよく、具体的なログの出力方法には依存しません。
C#8.0からは、インターフェースに「既定の実装(default implementation)」を書くことが可能になりました。
public interface IGreeter
{
void Greet() => Console.WriteLine("こんにちは!");
}
これは便利ですが、設計が複雑になりやすいため、必要な場面でのみ慎重に使うべきです。
インターフェースは継承の代替ではなく、「役割の分離」に強みがあります。すべてをインターフェースで済ませようとすると逆に設計が複雑になることもあるため、適材適所が大切です。
インターフェースを実装すると、すべてのメンバーを明示的に実装しなければならないため、コンパイルエラーで気づけるメリットもあります。
C#のインターフェースは、柔軟で拡張性のあるソフトウェア設計を実現するために欠かせない機能です。メソッドやプロパティの定義だけを記述することで、異なるクラス間で共通の契約を交わし、ポリモーフィズムやテストのしやすさ、コードの再利用性といった恩恵を得られます。
抽象クラスとの違いを理解し、必要に応じて使い分けることで、より堅牢で保守性の高いC#アプリケーションを開発できるようになります。ぜひ、インターフェースをマスターして、ワンランク上のC#開発者を目指しましょう。