インターフェース(Interface) にまつわる話。
インターフェースの基本
こういうインターフェースを作ると
public interfae IFoo{
string Greet(string to);
}
これは許されないが
public class FooImplementation : IFoo {
string Greet(string to, int i){
return "hello";
}
}
これは許される。
public class FooTypeA : IFoo {
string Greet(string to){
return $"hello {to}";
}
}
public class FooTypeB : IFoo {
string Greet(string to){
return $"こんにちは、{to} 様";
}
}
つまり "インターフェースで宣言したメソッドは実装クラスでその通りに実装されなければならない" という事。
良く知られた例としては IEnumerable<T> があり、いつも使う List&let;FooEntity> とかを foreach 出来るのも、string を foreach して1文字ずつ解析したりできるのも 実装クラスが必ずそう言う処理を実装しているから。
同じインターフェースに対する複数の実装
先の例の FooTypeA, FooTypeB は共に IFoo インターフェースを実装している。
これで何が嬉しいのかって言うのがイマイチ理解しづらいみたい。
サンプル
class Program{
public static void Main(string[] args){
IFoo foo = GetFoo(args[0]);
if(foo != null){
Console.Write(foo.Greet("Mr. Boo");
}
}
public static IFoo GetFoo(string fooType){
if(fooType "A") return new FooTypeA();
else if(fooType "B") return new FooTypeB();
else return null;
}
}
ここではコマンドライン引数で受け取ったタイプによって生成する実装クラス を切り替えて、メソッドGreet()を呼び出す。
void Mainを書く人はIFoo の実装クラスについてあまり詳細な事を知らなくても使える。
(ただし、自分の欲しい結果が何かは把握していないと困る)
つまり
- メソッドの形式が同じなので、インターフェースの定義を知っていれば使える
- 同じインターフェースを実装した複数のオブジェクトについて、同じメソッドを確実に呼び出すことができる(IDisposableなど = 常にusing{}できるとか)
- 何かの都合で処理内容を切り替えたい場合に使える
という事になる。
3番目の件、if や switch でどうにかすることもできるし、コンパイル定数で制御することもできるけども、テスト大変。