做过OO开发的人都清楚抽象类和接口,可是他们之间的区别和联系也许并不是那么容易区分
抽象类用来列举一个类所需要的行为但不明确提供每个行为的具体实现方法。当从以抽象基类派生一个类时,派生类将继承基类所有的特性,它可以通过override关键字用具体版本替换继承下来的抽象方法。如果该派生类没有从抽象基类继承下来的所有抽象方法提供具体实现,那么该派生类也是抽象类。
抽象类用来列举一个类所需要的行为但不明确提供每个行为的具体实现方法。当从以抽象基类派生一个类时,派生类将继承基类所有的特性,它可以通过override关键字用具体版本替换继承下来的抽象方法。如果该派生类没有从抽象基类继承下来的所有抽象方法提供具体实现,那么该派生类也是抽象类。
实现一个接口,概念上类似在扩充一个抽象类时填充其抽象方法,而两者的区别是:
1、对于接口我们只抽象行为(interface只能包含功能定义),而抽象类经常会包含具体的attribute,以及一些抽象行为和具体行为(abstract class可以包含功能定义和实现)。从某种程度来讲,接口要比抽象类更为抽象,因为接口留下了更多的想象空间
1、对于接口我们只抽象行为(interface只能包含功能定义),而抽象类经常会包含具体的attribute,以及一些抽象行为和具体行为(abstract class可以包含功能定义和实现)。从某种程度来讲,接口要比抽象类更为抽象,因为接口留下了更多的想象空间
抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征,因此反映的是事物的内部共性。例如苹果、香蕉、生梨、葡萄、桃子等,它们共同的特性就是水果。得出水果概念的过程,就是一个抽象的过程。要抽象,就必须进行比较,没有比较就无法找到共同的部分;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性。
2、当从一个抽象类派生一个非抽象类时,派生类通过覆载手段,提供抽象方法具体实现,其方法头一定会包括override关键字。
3、当一个类实现一个接口时,必须提供接口中声明的所有方法的具体实现。实现类并不覆载他们。
4、抽象类不一定要覆载基类的所有抽象方法,如果有一个或多个抽象方法没有覆载那么该派生类也是一个抽象方法。在抽象类中,新增一个方法的话,继承类中可以不用作任何处理;而对于接口来说,则需要修改继承类,提供新定义的方法。
5、一个类只能从一个基类派生,而一个类可以实现多个接口。
从语法上看两者的区别为:
1、两者表达的概念不一样。抽象类是一类事物的高度聚合,那么对于继承抽象类的子类来说,对于抽象类来说,属于“是”的关系;而接口是定义行为规范,因此对于实现接口的子类来说,相对于接口来说,是“行为需要按照接口来完成”。这些听起来有些虚,举个例子。例如,狗是对于所有狗类动物的统称,京哈是狗,牧羊犬是狗,那么狗的一般特性,都会在京哈,牧羊犬中找到,那么狗相对于京哈和牧羊犬来说,就属于这类事物的抽象类型;而对于“叫”这个动作来说,狗可以叫,鸟也可以叫。很明显,前者相当于所说的是抽象类,而后者指的就是接口。
2、抽象类可能会声明数据结构(attribute),而接口不声明attribtute.
3、抽象类使用关键字abstract声明抽象方法,并添加其可访问性,而接口不能加Public或者Abstract关键字。
4、抽象类可能会声明具体方法,而接口不声明具体方法(抽象类在定义类型方法的时候,可以给出方法的实现部分,也可以不给出;而对于接口来说,其中所定义的方法都不能给出实现部分)
5、基类从抽象类继承所有的attribute,而且可以添加attribute,而基类实现接口的时候必须提供自己的数据结构,而接口无法提供。
6、继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的抽象方法,可以不用重写,也就是说,可以延用抽象类的方法;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。
7、基类可以覆载从抽象类继承的抽象方,而基类必须全部实现接口的方法,无需使用override关键字。
7、基类可以覆载从抽象类继承的抽象方,而基类必须全部实现接口的方法,无需使用override关键字。
接口相对于抽象类的优势:
1、接口不光可以作用于引用类型,也可以作用于值类型。而抽象类来说,只能作用于引用类型。
2、.Net的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。
3、由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。
4、通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。
5、减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。
参看如下文章提供的方法。
http://blog.csdn.net/Knight94/archive/2006/10/08/1326326.aspx
2、.Net的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。其实,我对于这一点也比较赞同,多继承会使继承树变的混乱。
3、由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。
4、通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。
5、减少值类型的拆箱操作。对于Struct定义的值类型数据,当存放集合当中,每当取出来,都需要进行拆箱操作,这时采用Struct+Interface结合的方法,从而降低拆箱操作。
参看如下文章提供的方法。
http://blog.csdn.net/Knight94/archive/2006/10/08/1326326.aspx
相对于抽象类来说,接口有这么多好处,但是接口有一个致命的弱点,就是接口所定义的方法和属性只能相对于继承它的类型(除非在继承类中修改借口定义的函数标示),那么对于多层继承关系的时候,光用接口就很难实现。因为如果让每个类型都去继承接口而进行实现的话,首先不说编写代码比较繁琐,有时候执行的结果还是错误,尤其当子类型对象隐式转换成基类对象进行访问的时候。
那么这时候,需要用接口结合虚方法来实现。参看IDisposable在继承类型中的实现方法。
http://blog.csdn.net/Knight94/archive/2006/10/10/1329214.aspx
其实在继承中,到底使用接口还是抽象类。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。
如下给出两者的简单对比表格。
接口 抽象类
多继承 支持 不支持
类型限制 没有 有,只能是引用类型
方法实现 继承类型中必须给出方法实现 继承类中可以不给出
扩展性 比较麻烦 相对比较灵活
多层继承 比较麻烦, 需要借助虚函数 比较灵活
接口 抽象类
多继承 支持 不支持
类型限制 没有 有,只能是引用类型
方法实现 继承类型中必须给出方法实现 继承类中可以不给出
扩展性 比较麻烦 相对比较灵活
多层继承 比较麻烦, 需要借助虚函数 比较灵活
抽象类和接口的使用:
1、如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。
2、如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。
3、如果要设计大的功能单元,则使用抽象类;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
4、抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。
总的来说,接口和抽象类是.Net为了更好的实现类型之间继承关系而提供的语言手段,而且两者有些相辅相成的关系。因此并不强调用什么而不用什么,那么问题的关键在于,如何把这两种手段合理的应用到程序当中,这才是至关重要。
总结:
接口是负责功能的定义,项目中通过接口来规范类,操作类以及抽象类的概念! 而类是负责功能的具体实现!
在类中也有抽象类的定义,抽象类与接口的区别在于:
抽象类是一个不完全的类,类里面有抽象的方法,属性,也可以有具体的方法和属性,需要进一步的专业化。 但接口是一个行为的规范,里面的所有东西都是抽象的!
一个类只可以继承一个基类也就是父类,但可以实现多个接口.
<script type="text/javascript">var tagarray = 大学生编程交流;var tagencarray = 大学编程;parsetag();</script>
在类中也有抽象类的定义,抽象类与接口的区别在于:
抽象类是一个不完全的类,类里面有抽象的方法,属性,也可以有具体的方法和属性,需要进一步的专业化。 但接口是一个行为的规范,里面的所有东西都是抽象的!
一个类只可以继承一个基类也就是父类,但可以实现多个接口.