C#深入浅出 语法中各种比较(三)
1.类,结构
public struct Person { string Name; int height; int weight; public bool overWeight() { //implement something } }
public class TestTime { int hours; int minutes; int seconds; public void passtime() { //implementation of behavior } }
public class Test { public static ovid Main () { Person Myperson=new Person //声明结构 TestTime Mytime=New TestTime //声明类 } }
从上面的例子中我们可以看到类的声明和结构的声明非常类似
interface IImage { void Paint(); } struct Picture : IImage { public void Paint() { // painting code goes here } private int x, y, z; // other struct members }
public abstract class AbsTest { public virtual void Test() { Debug.WriteLine("Test"); } public abstract void NewTest(); } public interface ITest { void Test(); void NewTest(); }
继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的非抽象方法,可以不用重写,也就是说,可以延用抽象类的方法,对于抽象类中的抽象方法(隐式为虚方法),必须被覆盖,即若某个类继承了一个抽象类,则该类一定要实现基类中的抽象方法,不能不实现或者有选择的实现;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。在抽象类中,新增一个方法的话,继承类中可以不用作任何处理;而对于接口来说,则需要修改继承类,提供新定义的方法。
接口相对于抽象类的优势:
好处一,接口不光可以作用于引用类型,也可以作用于值类型。而抽象类来说,只能作用于引用类型。
好处二,.Net的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。
好处三,由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。
好处四,通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。
好处五,减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。
相对于抽象类来说,接口有这么多好处,但是接口有一个致命的弱点,就是接口所定义的方法和属性只能相对于继承它的类型(除非在继承类中修改接口定义的函数标示),那么对于多层继承关系的时候,光用接口就很难实现。因为如果让每个类型都去继承接口而进行实现的话,首先不说编写代码比较繁琐,有时候执行的结果还是错误,尤其当子类型对象隐式转换成基类对象进行访问的时候。
那么这时候,需要用接口结合虚方法来实现。其实在继承中,到底使用接口还是抽象类。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。
如下给出两者的简单对比表格:
|
接口 |
抽象类 |
多继承 |
支持 |
不支持 |
类型限制 |
没有 |
有,只能是引用类型 |
方法实现 |
继承类型中必须给出方法实现 |
继承类中可以不给出 |
扩展性 |
比较麻烦 |
相对比较灵活 |
多层继承 |
比较麻烦,需要借助虚函数 |
比较灵活 |