您选择使用接口而不是派生的原因是因为您想隐藏某事是如何完成的。如果你想表达一个类能够做某事,你可以使用接口。在这种情况下,您想证明 John 能够发出动物的声音。
这里问了同样的问题:
implements interface using member as implementor
解决方案是从猫中获得宠物主人。但是如果你必须实现两个接口呢?从两个类派生?
此外,PetOwner 不是猫。猫可以做很多宠物主人可能做不到的事情。
链接中给出的解决方案之一是从 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 不会自己哭,而是用他的猫哭。
问题是,如果您的 PetOwner 决定摆脱猫并购买狗,您的代码将不再有效。您使用 ICry 接口的计划行不通。
如果您真的想隐藏 PetOwner 的哭声,但又不想实现 ICry 的所有功能,请不要实现接口,而是实现一个 get 属性,该属性将为您提供一个实现 ICry 接口的对象。像这样:
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();
即使约翰决定摆脱他所有的动物和 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();