问题描述
假设我有一个接口ICry,它具有返回动物声音的函数:
Suppose, I have an interface ICry that has functions that return the sound of an animal:
public interface ICry
{
string Cry();
}
我有几个实现ICry的类:
class Cat:ICry
{
public string Cry {get {returnMeow!; }
}
I have several classes that implement ICry: class Cat : ICry { public string Cry { get { return "Meow!"; } } }
class Dog: ICry
{
public string Cry { get { return "Woof"; } }
}
如果我有一个拥有宠物的PetOwner对象,我知道这个PetOwner可以哭(),但想要隐藏他的哭声,我可以做以下事情:
If I have a PetOwner object that owns a pet, and I know this PetOwner can Cry(), but want to hide how he cries, I could do the following:
class PetOwner : ICry
{
private Cat cat = new Cat();
public string Cry() {return cat.Cry();}
}
然后用法是:
PetOwner john = new PetOwner();
console.WriteLine(john.Cry());
到目前为止,西部前线的一切都很安静
So far so good, everything quiet on the western front
但是,如果ICry有很多功能,该怎么办。使用此方法需要您为所有ICry函数实现PetOwner函数。虽然这些函数除了调用Cat.ICry的相应函数之外没有什么用处,但它仍然会有很多无用的工作。
But what to do if ICry has a lot of functions. Using this method obliges you to implement a PetOwner function for all ICry functions. Although these functions wouldn't do much more than call the corresponding function of Cat.ICry, it will still be a lot of useless work.
是否有防止出现的模式这个?
Is there a pattern to prevent this?
推荐答案
你选择使用界面而不是派生的原因是因为你想要隐藏某些事情的完成。如果要表示某个类能够执行某些操作,则使用接口。在这种情况下,你想要表明约翰能够产生动物的声音。
The reason why you would choose to use an interface instead of derivation is because you want to hide HOW something is done. You use an interface if you want to express that a class is capable of doing something. In this case you want to show that John is capable to produce an animal sound.
这里也问了同样的问题:
The same question was asked here:implements interface using member as implementor
解决方案是从猫那里派出宠物主人。但是如果你必须实现两个接口呢?从两个班派生?
The solution there was to derive the pet owner from the cat. But what if you have to implement two interfaces? Derive from two classes?
此外,PetOwner不是Cat。一只猫可以做很多PetOwner可能做不到的事情。
Besides, a PetOwner isn't a Cat. A cat can do a lot of things that a PetOwner probably can't.
链接中给出的一个解决方案是从PetOwner中删除ICry并给出PetOwner获得Cat的财产然后调用Cat的ICry函数:
One of the solutions given in the link is to remove the ICry from the PetOwner and give the PetOwner a property to get the Cat and then call the Cat's ICry functions:
class PetOwner
{
private Cat cat = new Cat();
public Cat Cat {return cat;}}
}
用法将是:
PetOwner John = new PetOwner();
John.Cat.Cry();
使用这种方法,PetOwners的用户必须知道PetOwner不会自己哭,而是使用他的猫哭了。
Using this method, users of PetOwners will have to know that the PetOwner will not cry himself, but uses his cat to cry.
问题是,如果你的PetOwner决定摆脱猫并买狗,你的代码就不再适用了。你使用ICry界面的计划不起作用。
The problem is, that if your PetOwner decides to get rid of the cat and buy a dog, your code doesn't work anymore. Your plan to use the ICry interface doesn't work.
如果你真的想要隐藏PetOwner的哭声,但你不想实现你的所有功能ICry,不实现接口,但实现了一个get属性,它将为您提供一个实现ICry接口的对象。像这样:
If you really want to hide how the PetOwner cries, but you don't want to implement all functions of you ICry, don't implement the interface, but implement a get property that will give you an object that implements the ICry interface. Like this:
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()已经完成了。因此,如果约翰决定带狗,并决定从现在起狗必须哭(),用户不必改变:
Now you don't know HOW John cries. You only know that John will take care that Cry() is done. So if John decide to take a dog, and decides that from now on the dog will have to Cry(), the user doesn't have to change:
class PetOwner
{
private Cat cat = new Cat();
private Dog dog = new Dog();
public ICry ICry {get{return dog;} }
}
用法未更改:
PetOwner John = new PetOwner();
John.ICry.Cry();
usage is not changed: PetOwner John = new PetOwner(); John.ICry.Cry();
即使John决定摆脱他所有的动物和Cry()本身用户也不必改变:
Even if John decides to get rid of all his animals and Cry() himself users don't have to change:
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();
John.ICry.Cry();
usage is still not changed: PetOwner John = new PetOwner(); John.ICry.Cry();
这篇关于如何将接口调用委托给实现该接口的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!