派生の代わりにインターフェイスを使用することを選択する理由は、何かがどのように行われるかを隠したいからです。クラスが何かを実行できることを表現したい場合は、インターフェイスを使用します。この場合、ジョンが動物の鳴き声を出すことができることを示したいとします。
同じ質問がここで尋ねられました:
実装者としてメンバーを使用してインターフェイスを実装します
そこでの解決策は、猫からペットの飼い主を導き出すことでした。しかし、2 つのインターフェースを実装する必要がある場合はどうでしょうか。2 つのクラスから派生しますか?
それに、PetOwner は猫ではありません。猫は、ペットの所有者がおそらくできない多くのことを行うことができます。
リンクに示されている解決策の 1 つは、PetOwner から ICry を削除し、PetOwner に Cat を取得するプロパティを与えてから、Cat の ICry 関数を呼び出すことです。
class PetOwner
{
private Cat cat = new Cat();
public Cat Cat {return cat;}}
}
使用法は次のとおりです。
PetOwner John = new PetOwner();
John.Cat.Cry();
この方法を使用すると、PetOwner のユーザーは、PetOwner が自分で泣くのではなく、猫を使って泣くことを知っている必要があります。
問題は、ペット所有者が猫を追い払って犬を買うことにした場合、コードが機能しなくなることです。ICry インターフェイスを使用するというあなたの計画はうまくいきません。
PetOwner の鳴き声を本当に隠したいが、ICry のすべての機能を実装したくない場合は、インターフェイスを実装せずに、ICry インターフェイスを実装するオブジェクトを提供する get プロパティを実装します。このような:
interface ICry
{
string Cry { get; }
}
class Cat : ICry
{
public string Cry { get { return "Meow!"; } }
}
class Dog: ICry
{
public string Cry { get { return "Woof"; } }
}
class PetOwner
{
private Cat cat = new Cat();
public ICry ICry {get{return cat;}}
}
使用法:
PetOwner John = new PetOwner();
John.ICry.Cry();
今、あなたはジョンがどのように泣くかを知りません。John が Cry() の実行を処理することだけはわかっています。したがって、John が犬を飼うことに決め、これから犬が Cry() を実行する必要があると判断した場合、ユーザーは次のように変更する必要はありません。
class PetOwner
{
private Cat cat = new Cat();
private Dog dog = new Dog();
public ICry ICry {get{return dog;} }
}
使用方法は変更されていません: PetOwner John = new PetOwner(); ジョン.ICry.Cry();
John がすべての動物と Cry() 自身を取り除くことにした場合でも、ユーザーは変更する必要はありません。
class PetOwner : ICry // The petowner has decide to Cry himself
{
public ICry ICry {get{return this;}}
public string Cry { get { return "Hello!"; } }
}
使用方法はまだ変更されていません: PetOwner John = new PetOwner(); ジョン.ICry.Cry();