显式与隐式(Explicit And Implicit)
1.概念
1.1 显式
实现的单词Explicit意思是清楚的、明确的、详述的。所以,显式的“显”是指明显且清楚的实现,相对于接口来说,就是明显而清楚的指定了接口的实现。对于其他的逻辑来说,显式就是清楚且明确的指定了实现内容。
1.2 隐式
实现的单词Implicit意思是隐匿的、不言明的、绝对的。所以,隐式的实现是指想当然的实现,相对于接口来说,只要实现类的方法签名和返回值与接口定义的一致即视为接口的实现,并无显式的(清晰的、明确的)指定。
2.例子
2.1 代码
1 using System; 2 namespace ExplicitAndImplicit{ 3 //刀子 4 public interface IKnife{ 5 void KillPeople(); 6 } 7 //枪 8 public interface IGun{ 9 void KillPeople(); 10 } 11 //隐式实现 12 public class WrongKillMachine:IKnife,IGun{ 13 public void KillPeople(){ 14 Console.WriteLine("切切切脑袋"); 15 } 16 } 17 //显式实现: 18 //1.实现接口方法不需要加访问定义符 19 //2.实现接口方法前面要加接口名.方法名,用来指定其实现的接口 20 //2.实现接口方法只能被显式的调用,不能被隐式的调用: 21 // 显式调用: 22 public class KillMachine:IKnife,IGun{ 23 void IKnife.KillPeople(){ 24 Console.WriteLine("切切切"); 25 } 26 void IGun.KillPeople(){ 27 Console.WriteLine("啪啪啪"); 28 } 29 } 30 public static class Case 31 { 32 public static void Begin(){ 33 Console.WriteLine("Design Pattern —— Explicit And Implicit:"); 34 //隐式实现 35 WrongKillMachine w = new WrongKillMachine(); 36 w.KillPeople(); 37 38 //显式实现 39 IKnife k = new KillMachine(); 40 k.KillPeople(); 41 IGun g = new KillMachine(); 42 g.KillPeople(); 43 } 44 } 45 }
2.2 结果
2.3 例子解释
2.3.1 隐式
实现即为WrongKillMachine类,并没有指定每个接口的实现方法,而是通过一个签名与返回值一致的方法来隐式实现(Implicit、不言明的、绝对的、隐匿的)。
2.3.2 显式
的实现即为KillMachine类,指定了每个接口实现的方法(KillPeople),相较于隐式的实现,它更加的清晰、明确、详述。
2.4 结合上面的例子写一个小故事
杀手跟他的助手说:“给我来一个能杀人的家伙”;
“用这个吧!”,助手从包里拿出了一个又像刀又像枪的家伙“这个是研究所刚刚给咱们研发的武器,外号杀人机器(KillMachine)‘要你命3000’,它集成了手枪与刀子的能力”
“怎么用呢?”杀手一知半解
“只要喊出语音指令‘KillPeople’,程式会自动执行的。”
“OK!”
杀手尾随它的目标来到车库,突然之间将无辜的John踢倒,用手锁住他的关节和身体并将自身的重量转移到上面,让John动弹不得。随后,他拿出了YaoNiMing3000,握住手柄,
慢慢的将枪口对准了John的心脏,心中默默为这位无辜的人祈祷着。“阿门......”。
"K-I-L-L,P-E-O-P-L-E!",响亮的吼声在无人的车库中回荡,John紧闭着双眼等待着死亡的来临。
“咔咔咔哒哒”,随着要你命3000中机械齿轮发出的声音,从枪口中“嗖”的一下,弹出一个一公分长的小刀。
John懵逼了。Σ( ° △ °|||)︴
杀手也懵逼了。Σ( ° △ °|||)︴
事后得知,是研发的博士让机器隐式实现了KillPeople方法,导致在调用的时候没有分开到底是具体哪一个功能的实现,结果功能都写到了一起,搞出了这个笑话。
所以,他将WrongKillMachine类停用,换成了KillMachine类,调用时也直接采用其抽象接口进行调用,这样就避免了一系列的问题,后期修改代码也更加方便了。
3.其他认证
3.1 关于一个类多个接口的实现既有显式也有隐式的规则(混合)
using System; namespace ExplicitAndImplicit { public interface InfA{ void Do(); } public interface InfB{ void Do(); } public interface InfC{ void Do(); } public interface InfD{ void Do(); } public class Class1:InfA,InfB,InfC,InfD{ void InfA.Do(){ Console.WriteLine("A"); } void InfB.Do(){ Console.WriteLine("B"); } public void Do(){ Console.WriteLine("C"); } } //测试目的是看多个接口实现是否可以部分显式、部分隐式,答案是肯定的 //同样,显式接口必须通过接口的声明实现 比如 Interface i = new Class(); public static class Case2_TestMultiIntegration{ public static void Begin(){ Utility.UnitStart(3,"1.2.1 Implicit-通过隐式方式调用隐式实现的借口 Class c = new Class(); c.DoMethod();"); Class1 c = new Class1(); c.Do(); Utility.UnitStart(3,"1.2.2 Explicit-通过显式方式调用显式方式实现的借口 Interface i = new Class(); i.DoMethod();"); InfA a = new Class1(); a.Do(); Utility.UnitStart(3,"1.2.3 MixedImplicit-通过显式方式调用隐式实现的接口 Interface i = new Class(); i.DoMethod();"); InfD d = new Class1(); d.Do(); } } }
3.2 结果:
4.应用原则
在逻辑比较复杂的情况下,比如一个类继承了多个接口,这些接口具有相同的行为,但却在实现上有差异(比较拗口,我觉得可以理解成平板电脑继承了MP3、CD、电脑的接口)的时候,再应用显式实现,大多数逻辑比较清晰的时候不需要用显式实现。是否必须要抽象出这么多有类似概念的接口也是一个课题,不过不在这个范围内讨论,关键是理解显式与隐式的概念。