C#などのオブジェクト指向プログラミングにおいて、「インターフェイス(Interface)」は非常に重要な役割を果たします。インターフェイスとは、クラスが実装すべき「機能の規格(契約)」を定義したものです。
インターフェイスを利用することで、具体的な処理内容(実装)と、利用するための窓口(定義)を切り離すことができ、柔軟で保守性の高いコードを記述できるようになります。今回は、メッセージ送信機能を題材に、インターフェイスの定義方法とクラスへの実装方法について解説します。
インターフェイスの基本構文
インターフェイスの定義には interface キーワードを使用します。慣習として、名前の先頭には「I」を付けます(例: ISample)。
- 定義できるもの: メソッド、プロパティ、イベント、インデクサの「シグネチャ(型や名前)」のみ。
- 定義できないもの: 実際の処理内容(メソッドの中身)や、フィールド(変数)。
- ※C# 8.0以降ではデフォルト実装が可能になりましたが、基本は「定義のみ」です。
実践的なコード例:メッセージ送信機能の規格化
以下のコードは、メッセージ送信機能を表す IMessageSender インターフェイスを定義し、それを具体的に実装した SmsSender クラスを作成する例です。
using System;
namespace MessagingSystem
{
class Program
{
static void Main()
{
// インターフェイス型の変数としてインスタンスを扱うことが可能です。
// これにより、具体的なクラス(SmsSender)の実装を知らなくても利用できます。
IMessageSender sender = new SmsSender();
sender.Send("090-1234-5678", "こんにちは。確認コードは 1234 です。");
sender.Send("080-9876-5432", "予約が完了しました。");
Console.WriteLine($"本日の送信合計数: {sender.SentCount} 件");
}
}
// 1. インターフェイスの定義
// クラスが「何をすべきか」という仕様だけを定義します。
public interface IMessageSender
{
// メソッドの定義(アクセシビリティ修飾子は書きません)
void Send(string recipient, string message);
// プロパティの定義(getのみ、setのみ、両方などを指定可能)
int SentCount { get; }
}
// 2. インターフェイスの実装
// クラス名の後ろに「: インターフェイス名」を記述します。
public class SmsSender : IMessageSender
{
// プロパティの実装
// インターフェイスでは get のみが規定されていますが、
// 実装側で private set を追加して内部で値を変更できるようにしています。
public int SentCount { get; private set; }
// メソッドの実装
// インターフェイスで定義されたメソッドを必ず public で実装する必要があります。
public void Send(string recipient, string message)
{
// 実際のSMS送信処理(ここではコンソール出力で代用)
Console.WriteLine($"[SMS送信] To: {recipient}, Body: {message}");
// 送信カウントをインクリメント
SentCount++;
}
}
}
実行結果
[SMS送信] To: 090-1234-5678, Body: こんにちは。確認コードは 1234 です。
[SMS送信] To: 080-9876-5432, Body: 予約が完了しました。
本日の送信合計数: 2 件
技術的なポイント
1. 契約としての役割
インターフェイスを実装(class SmsSender : IMessageSender)すると、そのクラスはインターフェイスで定義された全てのメンバー(メソッドやプロパティ)を必ず実装しなければなりません。これを守らないとコンパイルエラーになります。これにより、「このインターフェイスを持っているクラスなら、必ずSendメソッドを呼べる」という保証が生まれます。
2. プロパティの実装とアクセシビリティ
インターフェイス側で { get; } と定義されていても、実装クラス側で { get; set; } や { get; private set; } として実装することは可能です。インターフェイスは「最低限これが必要」という要件を示すものだからです。 ただし、実装するメンバーは必ず public である必要があります。
3. ポリモーフィズム(多態性)の活用
上記の Main メソッドのように、変数の型をインターフェイス型(IMessageSender)にしておくことで、代入するインスタンスを SmsSender から EmailSender や LineSender に切り替えたとしても、呼び出し側のコード(Sendメソッドを呼ぶ部分)を変更せずに済みます。これがインターフェイスを利用する最大のメリットの一つです。
まとめ
インターフェイスを定義することで、アプリケーションの「仕様」と「実装」を分離できます。最初は手間に感じるかもしれませんが、テストの容易性や将来的な機能拡張(例えばSMS以外の送信手段の追加など)を考慮すると、クラス設計において必須のテクニックとなります。
