はじめに
オブジェクト指向プログラミングにおいて重要な部分にも関わらず、初心者には理解が難しいインターフェイスについて解説する!
自分もここで躓いたので、他の人を救えるような記事にしたいと思って書きました。
インターフェース VS 抽象クラス
C#でインターフェイスと抽象クラスの違いは実はこれだけ!
インターフェース | 抽象クラス | |
---|---|---|
多重継承 | できる | できない |
フィールド | 持てない | 持てる |
※1 継承元の関数の影響を... | ※2 受けない | 受ける |
※1 継承元の影響とは関数のデフォルトの実装のことを言っています。
public virtual void SomeMethod()
{
// 継承先でオーバーライドされる前に実行したい共通処理
Console.WriteLine("共通の処理");
}
こんな感じで共通の処理の行のプログラムが書き換わった場合、全ての継承先に影響が伝播します。
※2 C# 8.0 でデフォルト実装ができるようになりました。しかし※1で説明した通り、interfaceの実装側で影響がいかないようにできるだけ使わない方が良いと考えています。
(要勉強)
要はインターフェイスは呼び出し元に対して「こういうメソッドがあるよ」と教えるためのものである!
...だから?
インターフェイスの使いどころ
良い例
ズバリ、インターフェイスを使うことは同じ関数を減らす営みである!
さっそく例を見てみよう!
interface IChatAI
{
string Chat(string message);
}
class ChatGPT : IChatAI
{
private string apiURL = "https://api/chatGPT";
public string Chat(string message)
{
string response = GetResponse(apiURL, message); // GetResponseは省略 messageを送信して返信を受け取る
return response;
}
}
class MyChat : IChatAI
{
public string Chat(string message)
{
if (message == "こんにちは")
{
return "こんにちは!";
}
else
{
return "わかんないや";
}
}
}
// 使い方
class Main
{
private ChatGPT chatAI;
private MyChat myChat;
public void Main(string[] args)
{
chatAI = new ChatGPT();
myChat = new MyChat();
Chat(chatAI, "こんにちは");
Chat(myChat, "こんにちは");
}
private void Chat(IChatAI chatAI, string message)
{
string response = chatAI.Chat(message);
Console.WriteLine(response);
}
}
この例では、IChatAIというインターフェイスを使ってChatGPTとMyChatを使い分けている。
このようにインターフェイスを使うことで、関数を呼び出すだけで処理を切り替えられる!
これがポリモーフィズムの力だ!
悪い例
class ChatGPT
{
private string apiURL = "https://api/chatGPT";
public string Chat(string message)
{
string response = GetResponse(apiURL, message); // GetResponseは省略 messageを送信して返信を受け取る
return response;
}
}
class MyChat
{
public string Chat(string message)
{
if (message == "こんにちは")
{
return "こんにちは!";
}
else
{
return "わかんないや";
}
}
}
// 使い方
class Main
{
private ChatGPT chatAI;
private MyChat myChat;
public void Main(string[] args)
{
chatAI = new ChatGPT();
myChat = new MyChat();
Chat(chatAI, "こんにちは");
Chat(myChat, "こんにちは");
}
private void Chat(ChatGPT chatAI, string message)
{
string response = chatAI.Chat(message);
Console.WriteLine(response);
}
private void Chat(MyChat chatAI, string message)
{
string response = chatAI.Chat(message);
Console.WriteLine(response);
}
}
お気づきだろうか? 同じような関数が2つもある!
このような状況に陥っている場合は抽象化がミスっている。
同じ部分を共通化するためにインターフェイスがある。
まとめ
インターフェースは
- 同じような関数を減らす
- 継承元の影響を受けない
という特徴がある。
Unityを扱った人はよく分かると思うが、Interfaceはコンポーネントのようなものです。
依存関係を減らすためにも、インターフェイスを使いこなせるようになろう!