设计模式-派生类实现非虚接口的陷阱
2017-03-04 17:24
405 查看
作者:vuefine
文献: msdn library
平台:.NET 2.0+
看一个例子。
定义接口ITest:
实现接口的Base类和Derive类
调用对象Base和Derive:
输出结果为:
可以看出,b和d实例的Test方法实现的行为都是位于基类的!!!这表明了,派生类不能覆写基类中实现接口的成员(非虚方法)
但是,请看下面调用:
输出结果为:
因此,如果想要继承的对象调用接口实现方法,只能声明为Derive实例。这样做不符合Effective C#中变量都声明为基实例的原则!!!
代码修改如下:
总结:
1、 派生不能覆写接口的非虚成员;
2、如果派生类方法是个性方法,将基类方法转为虚方法;
3、若基类实现了接口方法,将派生类也显示地继承此接口,但是不用再次实现了!!!
文献: msdn library
平台:.NET 2.0+
理解接口方法和虚方法的区别
第一眼看来,实现接口和覆写虚方法似乎没有什么区别,实际上,实现接口和覆写虚方法之间的差别很大!!!派生不能覆写接口的非虚成员
接口中声明的成员方法默认情况下并非虚方法,所以,派生类不能覆写基类中实现接口的非虚成员。看一个例子。
定义接口ITest:
public interface ITest { void Test(); }
实现接口的Base类和Derive类
public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } //实现ITest接口 public void Test() { Console.WriteLine("This is in base to ITest implement"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } //测试Derive类实现了ITest吗?? public void Test() { Console.WriteLine("This is in Derive to ITest implement"); } }
调用对象Base和Derive:
Base b = new Base(); b.Test(); Base d = new Derive();//将d声明为Base对象 d.Test(); Console.ReadLine();
输出结果为:
可以看出,b和d实例的Test方法实现的行为都是位于基类的!!!这表明了,派生类不能覆写基类中实现接口的成员(非虚方法)
但是,请看下面调用:
Base b = new Base(); b.Test(); Derive d = new Derive(); //将d声明为Derive对象 d.Test(); Console.ReadLine();
输出结果为:
因此,如果想要继承的对象调用接口实现方法,只能声明为Derive实例。这样做不符合Effective C#中变量都声明为基实例的原则!!!
派生类方法个性,将基类方法转为虚方法
避免这种使用上的混淆,如果确实派生类实现方法是个性行为,那么需要将基类的实现接口的方法前加virtual修饰符!代码修改如下:
public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } public virtual void Test() //实现ITest接口的虚方法 { Console.WriteLine("This is in base to ITest implemnt"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } public override void Test() //实现接口ITest的复写方法 { Console.WriteLine("This is in Derive to ITest implemnt"); } }
一次实现,多个关联对象使用
观察上面的代码,我们发现,在基类中实现的接口,如果派生类也想实现此接口,那么它默认继承了基类的接口实现,所以不用重复写代码实现接口。public interface ITest { void Test(); } public class Base:ITest { public Base() { Console.WriteLine("This is base constructor"); } public void Test() { Console.WriteLine("This is in base to ITest implemnt"); } } public class Derive :Base,ITest { public Derive() { Console.WriteLine("This is derived constructor"); } }
总结:
1、 派生不能覆写接口的非虚成员;
2、如果派生类方法是个性方法,将基类方法转为虚方法;
3、若基类实现了接口方法,将派生类也显示地继承此接口,但是不用再次实现了!!!
相关文章推荐
- 设计模式实践-反射到所有接口实现类实践工厂方法,页面中有大量计算数据时设计实践
- 设计模式之Programming to an Interface, not anImplementation 程序指向接口,而不是实现
- 设计模式(一)单例模式:实现 Serializable 接口之后的额外操作
- Javascript乱弹设计模式系列(0) - 面向对象基础以及接口和继承类的实现
- 设计模式:对于一种类,有可能需要在其执行前,中,后,插入一些代码,留下接口,让调用者实现
- 通过Observable类和Observer接口实现观察者设计模式
- php使用接口实现工厂设计模式
- java 抽象类实现接口是什么设计模式
- php中使用接口实现工厂设计模式的代码
- [设计模式]接口代理实现Application的多继承
- 设计模式:Interface Inheritance (接口继承)和 Implementation Inheritance(实现继承)
- 设计模式之Programming to an Interface, not anImplementation 程序指向接口,而不是实现
- GOF23设计模式之观察者模式的理解与实现2(使用java自带的观察者类和接口)
- Android中设计模式--策略模式(封装会变化的算法部分,面向接口不针对实现)
- php中使用接口实现工厂设计模式的代码
- C#设计模式之 :Abstract_Factory模式(使用接口实现)
- 抽象类实现多个接口与接口的继承的对比,实现良好的设计模式!
- 适配器(Adapter)设计模式和接口实现完全解耦
- 《第一行代码Java》接口实现代理设计模式(Proxy)笔记与代码
- 《模式――工程化实现及扩展》(设计模式C# 版)《连贯接口 Fluent Interface》――“自我检验"参考答案