interface
が interface
を継承するって?
正直言って、これは行儀の良い作法ではない。アンチパターン一歩手前である。しかし、C#の文法的に許されていることだし、利点も十分あるので議論の価値はあるだろう。
即ち、以下の様なコードである。
public interface IFoo
{
int DoSomething();
}
public interface IBar : IFoo
{
double DoOtherThing();
}
public class SomeClass : IBar
{
/// <summary>
/// IFooのメソッド実装。IBarには書かれていないが、継承しているため実装が必要。
/// </summary>
public int DoSomething()
{
return 530000;
}
/// <summary>
/// IBarのメソッド実装。
/// </summary>
public double DoOtherThing()
{
return 5.55;
}
}
長所
-
IFoo
が必要となるメソッドにIBar
のインスタンスを入れることができる。 -
SomeClass
にはIFoo
を明示的に実装しなくてもIFoo
に変換可能。
interface
からinterface
を派生させたいということは割とある(例えばモジュールのinterface
を結合したinterface
を作るなど)ので、それなりに需要はあると思う。
短所
-
IFoo
を見るだけではIFoo
がどのメソッドを要求しているかが分からない。 -
SomeClass
がIFoo
インターフェイスを実装していることがコードだけでは分からない。
一応、どのメソッドを実装すべきかはVisual StudioなどのIDEが教えてくれるだろうが、分かりづらいことは確かである。
interface
でメンバが被った場合
当然ながらinterface
は多重継承できる。その場合に発生するのがメンバ被りだ。例えば次の場合を考える。
public interface IHoge
{
int Something { get; set; }
// その他メンバ省略
}
public interface IPiyo
{
int Something { get; set; }
// その他メンバ省略
}
public interface IFuga : IHoge, IPiyo
{
// その他メンバ省略
}
public class Fuga : IFuga
{
public int Something { get; set; }
// その他実装は省略
}
public void main()
{
IFuga fuga = new Fuga();
fuga.Something; // ここで警告が出る!
}
IFuga
はコードのどこかでIHoge
、IPiyo
として使われることを期待している。
しかし、IFuga
経由で両方で定義されているメンバを読み出すと、警告が走る。この場合は型が同じなので警告に留まるが、型が違えばそれぞれを明示的に実装しなければならないし、fuga.Something
という書き方はできない。
この場合の解法:new宣言の使用
ここでfuga.Something
としたいのであれば、IFugaを以下のコードを追加すれば良い。
public interface IFuga : IHoge, IPiyo
{
// ...
new int Something { get; set; }
}
new
と銘打ったことでIFuga.Something
は上位クラスとのつながりが切れた。しかし、今回の場合は型が同じため、IHoge
、IPiyo
いずれからでもSomething
を読み出すことができる。