- 一、均可以被继承
- 二、都不能被实例化
- 三、均可以包含方法声明
- 四、派生类必须实现未实现的方法
区别:
- 一、抽象基类能够定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
- 二、抽象类是一个不完整的类,须要进一步细化,而接口是一个行为规范。微软的自定义接口老是后带able字段,证实其是表述一类“我能作。。。”
- 三、接口能够被多重实现,抽象类只能被单一继承
- 四、抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中
- 五、抽象类是从一系列相关对象中抽象出来的概念,所以反映的是事物的内部共性;接口是为了知足外部调用而定义的一个功能约定, 所以反映的是事物的外部特性
- 六、接口基本上不具有继承的任何具体特色,它仅仅承诺了可以调用的方法
- 七、接口能够用于支持回调,而继承并不具有这个特色
- 八、抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,固然您也能够声明为虚的
- 九、若是抽象类实现接口,则能够把接口中方法映射到抽象类中做为抽象方法而没必要实现,而在抽象类的子类中实现接口中方法
使用规则:
- 一、抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能
- 二、若是要设计大的功能单元,则使用抽象类;若是要设计小而简练的功能块,则使用接口。
- 三、若是预计要建立组件的多个版本,则建立抽象类。接口一旦建立就不能更改。若是须要接口的新版本,必须建立一个全新的接口。
- 四、若是建立的功能将在大范围的全异对象间使用,则使用接口;若是要在组件的全部实现间提供通用的已实现功能,则使用抽象类。
- 五、分析对象,提炼内部共性造成抽象类,用以表示对象本质,即“是什么”。为外部提供调用或功能须要扩充时优先使用接口
- 六、好的接口定义应该是具备专注功能性的,而不是多功能的,不然形成接口污染。若是一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其余方法,就叫接口污染
- 七、尽可能避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。由于继承的层次增多,形成最直接的后果就是当你调用这个类群中某一类,就必须把他们所有加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友能够留意到微软在构建一个类时,不少时候用到了对象组合的方法。好比 asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是很是基本的一个设计原则
例如:
Window窗体能够用抽象类来设计,能够把公有操做和属性放到一个抽象类里,让窗体和对话框继承自这个抽象类,再根据本身的需求进行扩展和完善。编程
打印操做能够做为一个接口提供给每一个须要此功能的窗体,由于窗体的内容不一样,就要根据他们本身的要求去实现本身的打印功能。打印时只经过接口来调用,而不用在意是那个窗体要打印。设计模式
共性、个性与选择:
有的书上写到C#推荐使用接口(Interface)来替代抽象基类(Abstract Class),并强调使用接口的诸多好处,这点我不敢苟同,从上面列表中看来,二者之间仍是存在很多差别的,而这种差别的存在性必然决定了适用场景的不一样,例如在抽象基类中能够为部分方法提供默认的实现,从而避免在子类中重复实现它们,提升代码的可重用性,这是抽象类的优点所在;而接口中只能包含抽象方法。至于什么时候使用抽象基类什么时候使用接口关键仍是取决于用户是如何看待继承类之间的联系的,用户更加关心的是它们之间的个性差别仍是它们之间的共性联系。举个生活中的例子加以说明。asp.net
若是给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来归纳它们之间的联系,那么首先给你的感受确定是它们个体间的差别性较大,很难抽象出共性,然而若让你归纳他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,缘由有三条:ide
1 interface ISwim
2 {
3 void Swim();
4 }
5
6 public class Person : ISwim
7 {
8 public void Swim()
9 {
10 //Swimming in person's style.
11 }
12 }
13
14 public class Frog : ISwim
15 {
16 public void Swim()
17 {
18 //Swimming in frog's style.
19 }
20 }
21
22 public class Fish : ISwim
23 {
24 public void Swim()
25 {
26 //Swimming in fish's style.
27 }
28 }
- 一、个性大于共性。
- 二、差别较大的个性间具备某些相同的行为。
- 三、相同行为的实现方式有较大区别。
这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来归纳它们之间的联系,那么你第一个意识到的确定是它们都属于鱼类,其次是他们游泳的方式可能稍有差别,这时就应当使用抽象基类而不是接口,对比着上面的例子,缘由也有三条:post
1 abstract public class Fish
2 {
3 abstract public void Swim();
4 }
5
6 public class 鲫鱼 : Fish
7 {
8 public override void Swim()
9 {
10 //Swim like a 鲫鱼
11 }
12 }
13
14 public class 鲤鱼 : Fish
15 {
16 public override void Swim()
17 {
18 //Swim like a 鲤鱼
19 }
20 }
21
22 public class 金鱼 : Fish
23 {
24 public override void Swim()
25 {
26 //Swim like a 金鱼
27 }
28 }
- 一、共性大于个性
- 二、共性相同的个体间必然具备相同的属性与行为
- 三、相同行为的实现方式具备必定区别
观察在使用接口或是使用抽象基类的几条理由中,第三条理由实际上是同样的,它所描述的是面向对象中多态的概念,即经过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。第二条理由开始产生分歧,接口更增强调了继承对象间具备相同的行为,而抽象类同时还强调了继承对象间具备相同的属性。而真正将接口与抽象基类区分开的则是理由概括以下:学习
- 当在差别较大的对象间寻求功能上的共性时,使用接口。
- 当在共性较多的对象间寻求功能上的差别时,使用抽象基类。
经过相同与不一样的比较,咱们只能说接口和抽象类,各有所长,但无优略。在实际的编程实践中,咱们要视具体状况来酌情量才,可是如下的经验和积累,或许能给你们一些启示,除了个人一些积累以外,不少都来源于经典,我相信经得起考验。因此在规则与场合中,咱们学习这些经典,最重要的是学以至用,固然我将以一家之言博你们之笑,看官请继续。spa
规则与场合:
- 一、请记住,面向对象思想的一个最重要的原则就是:面向接口编程。
- 二、借助接口和抽象类,23个设计模式中的不少思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程。
- 三、抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
- 四、接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系;
- 五、接口多定义对象的行为;抽象类多定义对象的属性;
- 六、接口定义可使用public、protected、internal 和private修饰符,可是几乎全部的接口都定义为public,缘由就没必要多说了。
- 七、“接口不变”,是应该考虑的重要因素。因此,在由接口增长扩展时,应该增长新的接口,而不能更改现有接口。
- 八、尽可能将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。
- 九、接口名称前面的大写字母“I”是一个约定,正如字段名如下划线开头同样,请坚持这些原则。
- 十、在接口中,全部的方法都默认为public。
- 十一、若是预计会出现版本问题,能够建立“抽象类”。例如,建立了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对之后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改全部派生类,并从新编译,因此版本式的问题最好以抽象类来实现。
- 十二、从抽象类派生的非抽象类必须包括继承的全部抽象方法和抽象访问器的实实现。
- 1三、对抽象类不能使用new关键字,也不能被密封,缘由是抽象类不能被实例化。
- 1四、在抽象方法声明中不能使用 static 或 virtual 修饰符。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fxh_hua/archive/2009/08/20/4464739.aspx.net