私は現在、C#のインターフェイスについて読んだり学習したりしており、これまでのところ、抽象クラスとの違いを理解することができました。本を読んでいる筆者は、インターフェイスは究極の抽象クラスであり、継承クラスが持つ特定のメソッドの標準を設定するだけであると説明していますが、次の例を示します。
static void Main(string[] args)
{
...
Circle c = new Circle("Lisa");
IPointy itPt = null;
try
{
itPt = (IPointy)c;
Console.WriteLine.(itPt.Points);
}
catch (InvalidCastException e)
{
Console.WriteLine(e.Message);
}
...
}
絶対に私を捨てる行はIPointy itfPt=null;
彼はインターフェースを宣言しただけですか?インターフェイスは抽象的で、継承しかできないと思いましたか?ここではどのような魔術が行われていますか?
その例は、何よりもtry ... catchを示しています。
インターフェースも型ですが、それらはコントラクトを公開するだけです。したがって、この:
IPointy itPt = new IPointy();
..動作しません。このことを考慮:
interface IPointy {
void MyMethod();
}
class Pencil : IPointy {
void MyMethod() {
}
void MyOtherMethod() {
}
}
次のようにIPointyを宣言できます。
IPointy itPt = new Pencil();
..しかし、これはうまくいきます:
itPt.MyMethod();
..これは機能しません:
itPt.MyOtherMethod();
これは、MyMethod
がIPointyコントラクトの一部であるためです。MyOtherMethod
はそうではありません。
編集:私のコメントを説明するためにこれを拡張します。
クラスからの継承は「is-a」関係を表します。インターフェースの実装は、「できる」関係を表します。
考慮してください:
interface ISwitchable {
void SwitchOn();
void SwitchOff();
}
class Light : ISwitchable {
void SwitchOn() { }
void SwitchOff() { }
}
class Television : ISwitchable {
void SwitchOn() { }
void SwitchOff() { }
}
テレビとライトはどちらもISwitchableから継承しています。インターフェースは「実行可能な」関係を定義します。両方をオンまたはオフに切り替えることができます。次のコードブロックはどちらも有効です。
ISwitchable mySwitchableObject1 = new Light();
ISwitchable mySwitchableObject2 = new Television();
mySwitchableObject1.SwitchOn(); // calls Light's SwitchOn method
mySwitchableObject2.SwitchOn(); // calls Television's SwitchOn method
インターフェイスとして型指定された変数を宣言できます。これはインスタンス化に相当しません。インターフェース型の変数を宣言したら、インターフェースを実装するanyクラスのオブジェクトをその変数に割り当てることができます。
たとえば、インターフェイスタイプIDictionary<string,string>
の変数を宣言できますが、インスタンス化することはできません。たとえば、IDictionary<string,string>
を実装するクラスを選択する必要があります。次に例を示します。
IDictionary<string,string> d = new Dictionary<string,string>();
または
IDictionary<string,string> d = new SortedList<string,string>();
インターフェイスは、そのキーワード行に含まれていないインターフェイスキーワードを使用して宣言されます。
表示されているのは、変数宣言、itfPtという名前の変数で、その型はIPointyです。変数はインスタンスではない値「null」を取得します。
インターフェイスIPointyをインスタンス化することはできません。次のように入力してみてください。itfPt = new IPointy();コンパイルエラーを調べます。 itfPtに割り当てることができる唯一の値は、IPointyおよびnullの具象サブタイプのインスタンスです。
あなたが探しているのは、インターフェースのインスタンス化とそれの使用だと思います。ここにあなたを助けるかもしれない例があります:
public interface IFoo
{
void Bar1();
void Bar2();
}
public Class ActionableFoo : IFoo
{
Action _bar1, _bar2;
public ActionableFoo(Action b1, Action b2)
{
_bar1 = b1;
_bar2 = b2;
}
public void Bar1() { if(_bar1 != null) _bar1(); }
public void Bar2() { if(_bar2 != null) _bar2(); }
}
public void PushFoo(Action bar1, Action bar2)
{
IFoo foo = new ActionableFoo(bar1, bar2);
_fooStack.Push(foo);
}