近日看到了一个贴子,就是在C#语言中,如何实现多担任的问题。相信涉猎c#不久不多的人(像我这样的菜鸟),一看就感受很可笑,c#必定是不能实现多担任的啊。都知道在c++中因为实现多担任会有很多的歧义问题,所以在c#中就把多担任给打消了,而用接口来实现!但是想想,如果是初学者必定不会不会问这样的问题。必定是个妙手,然后就开始上网查资料!然后发明真的可以实现!
说起多担任,首先大家可以想想这个问题:你知道在C#中怎么实现多担任吗?
主流的答案无非2种。
答案一:用接口啊,一个类可以担任自多个接口的。
答案二:C#不撑持多担任,C++才撑持多担任,多担任会让代码变得很乱,因此微软在设计C#的时候放弃了多担任。
能够知道答案二的人显然懂的更多,我也在很长一段时间内相信C#不撑持多担任,直到2013年5月的一个项目中,我偶然的发明本身的代码就完全实现了真正意义的多担任。
先说说什么是真正意义的多担任。真正的多担任应该是像C++那样的,而不是说像在C#里面一个类担任了多个接口就叫多担任。在C#中,如果一个类实现了多个接口,那么要为每个接口写实现,如果接口被多个类担任,那么就会有反复的代码,这显然是无法接受的。
然而C++那样的多担任也确确实实给编码带来了很大的麻烦,我也相信微软真的是因为意识到了多担任的不同理之处才在C#中摈斥了这个特性。而我在C#中实现的多担任,第一是真正的多担任,第二代码写的很合理。
请看案例
假如你有一个类叫老虎,还有一个类叫苍蝇。此刻你想新创一个超级老虎类,一种可以飞的老虎。在C++中,你可以界说一种超级老虎类,让其担任自老虎和苍蝇,这样这种老虎就可以飞了。然而,问题呈现了,这种超级老虎由于同时也担任自苍蝇,而苍蝇下面有个要领叫吃,参数类型是屎。吃屎的这个要领显然跟我们的超级老虎太不搭了。
虽然这个例子有些夸张,但是很多C++措施员真的就是这样在设计代码。由于子类担任了多个父类,而多个父类必定有些成员跟这个子类不搭调,于是子类的挪用者就很难受了。好比上面这个例子,当挪用者拿到超级老虎的一个实例时,发明超级老虎下面怎么会有个吃屎的要领呢!!!真的是要笑死人了。
C++要这样允许多担任就一定会造成这个问题。C#措施员就绝对不会写出这样风趣的代码。对付C#措施员,必定是要把这个飞的要领提成接口的,,然后让苍蝇类和超级老虎类都担任自这个接口。这样,苍蝇会飞,超级老虎也会飞。是不是完美解决这个问题?
问题看上去解决了,但是,假如我跟你说苍蝇飞的要领跟超级老虎飞的要领需要一模一样:首先张开双翅,身体前倾,拍打双翅,起飞,继续拍打。我们必定不能把同一份代码copy一份吧,那是属于入门级措施员干的事,我们此刻已经没资格干那事了。那怎么办呢?简单快速的做法是使用静态要领,好比FlyHelper.Fly(…)。
静态要领解决了代码重用的问题,但写起来始终感受哪里不同错误劲。我的超级老虎类和苍蝇都明明担任了飞了啊,为什么还要这样挪用一句静态要领。如果以后哪天我想让我的猪也能飞起来,那岂不是还要来挪用这个静态要领。
到底怎样才华在C#中实现像C++那样优雅的担任呢?
答案揭晓
答案其实很简单,那就是给IFly接口写扩展要领。
首先请看这个空接口的界说,及其扩展要领(注意泛型限制):
代码如下:
namespace Interface
{
//飞的接口
public interface IFly
{
}
//扩展要领
public static class ExtendFly
{
public static void StartFly<T>(this T example) where T : IFly
{
Console.WriteLine(“筹备”);
Console.WriteLine(“张开双翅”);
Console.WriteLine(“起飞”);
Console.WriteLine(“我飞,我飞,我飞飞飞”);
}
}
}
再看老虎和苍蝇的实现:
代码如下:
namespace Interface
{
//苍蝇类实现飞的接口
public class flies : IFly
{
public void fly()
{
//挪用接口中飞的要领
this.StartFly();
}
}
}
namespace Interface
{
//老虎类
public class Tiger
{
public void introduce()
{
Console.WriteLine(“I am a tiger”);
}
}
}
再看超级老虎的实现:
代码如下: