相同点:

  • 1、都可以被继承
  • 2、都不能被实例化
  • 3、都可以包含方法声明
  • 4、派生类必须实现未实现的方法

区别:

  • 1、抽象基类可以定义字段、属性、方法实现。接口只能定义属性、索引器、事件、和方法声明,不能包含字段。
  • 2、抽象类是一个不完整的类,需要进一步细化,而接口是一个行为规范。微软的自定义接口总是后带able字段,证明其是表述一类“我能做。。。”
  • 3、接口可以被多重实现,抽象类只能被单一继承
  • 4、抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中
  • 5、抽象类是从一系列相关对象中抽象出来的概念,因此反映的是事物的内部共性;接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性
  • 6、接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法
  • 7、接口可以用于支持回调,而继承并不具备这个特点
  • 8、抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的
  • 9、如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法

使用规则:

  • 1、抽象类主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能
  • 2、如果要设计大的功能单元,则使用抽象类;如果要设计小而简练的功能块,则使用接口。
  • 3、如果预计要创建组件的多个版本,则创建抽象类。接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。
  • 4、如果创建的功能将在大范围的全异对象间使用,则使用接口;如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
  • 5、分析对象,提炼内部共性形成抽象类,用以表示对象本质,即“是什么”。为外部提供调用或功能需要扩充时优先使用接口
  • 6、好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染
  • 7、尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知。(结合堆栈原理理解)。同时,有心的朋友可以留意到微软在构建一个类时,很多时候用到了对象组合的方法。比如 asp.net中,Page类,有Server Request等属性,但其实他们都是某个类的对象。使用Page类的这个对象来调用另外的类的方法和属性,这个是非常基本的一个设计原则

例如:

Window窗体可以用抽象类来设计,可以把公有操作和属性放到一个抽象类里,让窗体和对话框继承自这个抽象类,再根据自己的需求进行扩展和完善。

打印操作可以作为一个接口提供给每个需要此功能的窗体,因为窗体的内容不同,就要根据他们自己的要求去实现自己的打印功能。打印时只通过接口来调用,而不用在乎是那个窗体要打印。

共性、个性与选择:

有的书上写到C#推荐使用接口(Interface)来替代抽象基类(Abstract Class),并强调使用接口的诸多好处,这点我不敢苟同,从上面列表中看来,两者之间还是存在不少差异的,而这种差异的存在性必然决定了适用场景的不同,例如在抽象基类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,提高代码的可重用性,这是抽象类的优势所在;而接口中只能包含抽象方法。至于何时使用抽象基类何时使用接口关键还是取决于用户是如何看待继承类之间的联系的,用户更加关心的是它们之间的个性差异还是它们之间的共性联系。举个生活中的例子加以说明。

如果给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来概括它们之间的联系,那么首先给你的感觉肯定是它们个体间的差异性较大,很难抽象出共性,然而若让你概括他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,原因有三条:

 1 interface ISwim2         {3             void Swim();4         }5 6         public class Person : ISwim7         {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         }

  • 1、个性大于共性。
  • 2、差异较大的个性间具有某些相同的行为。
  • 3、相同行为的实现方式有较大区别。

这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来概括它们之间的联系,那么你第一个意识到的肯定是它们都属于鱼类,其次是他们游泳的方式可能稍有差异,这时就应当使用抽象基类而不是接口,对比着上面的例子,原因也有三条:

 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 }

  • 1、共性大于个性
  • 2、共性相同的个体间必然具有相同的属性与行为
  • 3、相同行为的实现方式具有一定区别

观察在使用接口或是使用抽象基类的几条理由中,第三条理由其实是一样的,它所描述的是面向对象中多态的概念,即通过覆盖父类的方法来实现,在运行时根据传递的对象引用,来调用相应的方法。第二条理由开始产生分歧,接口更加强调了继承对象间具有相同的行为,而抽象类同时还强调了继承对象间具有相同的属性。而真正将接口与抽象基类区分开的则是理由归纳如下:

  • 当在差异较大的对象间寻求功能上的共性时,使用接口。
  • 当在共性较多的对象间寻求功能上的差异时,使用抽象基类。

通过相同与不同的比较,我们只能说接口和抽象类,各有所长,但无优略。在实际的编程实践中,我们要视具体情况来酌情量才,但是以下的经验和积累,或许能给大家一些启示,除了我的一些积累之外,很多都来源于经典,我相信经得起考验。所以在规则与场合中,我们学习这些经典,最重要的是学以致用,当然我将以一家之言博大家之笑,看官请继续。

规则与场合:

  • 1、请记住,面向对象思想的一个最重要的原则就是:面向接口编程。
  • 2、借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程。
  • 3、抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。
  • 4、接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系;
  • 5、接口多定义对象的行为;抽象类多定义对象的属性;
  • 6、接口定义可以使用public、protected、internal 和private修饰符,但是几乎所有的接口都定义为public,原因就不必多说了。
  • 7、“接口不变”,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增加新的接口,而不能更改现有接口。
  • 8、尽量将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。
  • 9、接口名称前面的大写字母“I”是一个约定,正如字段名以下划线开头一样,请坚持这些原则。
  • 10、在接口中,所有的方法都默认为public。
  • 11、如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)来应对以后可能出现风马牛的事情。而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。
  • 12、从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。
  • 13、对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。
  • 14、在抽象方法声明中不能使用 static 或 virtual 修饰符。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fxh_hua/archive/2009/08/20/4464739.aspx

c#中抽象类(abstract)和接口(interface)的相同点与区别相关推荐

  1. 晋南讲堂之Java抽象类(abstract)与接口(interface)区分

    抽象类(abstract)和接口(interface)的对比 1. 抽象类(abstract)   我们一般声明一个抽象类按照如下形式: abstract class ClassName{//成员变量 ...

  2. 浅谈C#中的抽象类(abstract)和接口(interface)

    很多C#的初学者在编程时都容易把抽象类和接口搞混,甚至很多编程老鸟也没有弄明白为什么有了抽象类又搞个接口(这里也包括了本老鸟).所以这里整理了C#抽象类和接口的区别,详细的分析了抽象类与接口的概念与特 ...

  3. JAVA面向对象OOP多态→抽象类abstract、接口interface实现implement、final不变修饰符、样例代码

    抽象类 抽象类-接口关系示意图 如果一个类实现接口,就要把接口中所有的抽象方法都重写. A接口继承另一个B接口时,类要重写AB两个接口的方法 如果只是实现部分接口,可以用抽象类实现. 抽象类与接口不同 ...

  4. Java中抽象类 abstract和interface的区别

    abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力. abstract class和inte ...

  5. sql语句和java的关系_java中Statement 与 PreparedStatement接口之间的关系和区别

    Statement 和 PreparedStatement之间的关系和区别. 关系:PreparedStatement继承自Statement,都是接口 区别:PreparedStatement可以使 ...

  6. Dart中抽象类 多态以及接口

    Dart中抽象类:Drat抽象类主要是用于定义标准,子类可以继承抽象类,也可以实现抽象类接口. 1.抽象类通过abstract关键字来定义 2.Drat中的抽象方法不能用abstract声明,Dart ...

  7. abstract类和接口interface的联系和区别

    一,用关键字abstract类修饰的类称为abstract类(抽象类). abstract class A{ ----. } 特点: 1. 抽象类中可以有抽象方法和非抽象方法,但是抽象方法只允许声明不 ...

  8. 接口和和抽象的区别总结

    抽象类 类可以定义为抽象类 有抽象方法的类都是抽象类 抽象方法应用场景: 方法的实现没想好 无法统一子类的实现 如果父类中有抽象方法,子类不实现,子类必须为抽象类 抽象类不能被实例化 抽象类不能用ab ...

  9. php 类 接口的区别吗,PHP的接口类(interface)和抽象类(abstract)的区别

    /** * 接口类:interface * 其实他们的作用很简单,当有很多人一起开发一个项目时,可能都会去调用别人写的一些类, * 那你就会问,我怎么知道他的某个功能的实现方法是怎么命名的呢,这个时候 ...

最新文章

  1. 定义ComboBox(下拉列表)组件垂直滚动条的样式。
  2. 李沐团队提出最强ResNet改进版,多项任务达到SOTA | 已开源
  3. Django框架(5.django中模型类建立关系和多表关系查询)
  4. ubuntu搭建nodejs生产环境——快速部署手册
  5. 赛门铁克调研发现越来越多的物联网设备被用于实施DDoS攻击
  6. 87.http upstream模块提供的变量
  7. 编写项目工作说明书(SOW)
  8. 建模实训报告总结_建模实习工作总结
  9. (详细)Windows10系统自动修复方法
  10. vit transformer中的cls_token
  11. 数据分析与爬虫实战视频——学习笔记(二)(千图网图片爬虫、fiddler抓包分析、腾讯视频评论爬虫、多线程爬虫(糗百))
  12. java笔记之基础-outer标签
  13. FSM有限状态机设计(Logisim)
  14. muduo源码学习 Day03
  15. 4、Arduino_esp32 ADC使用
  16. 讲述做程序员的发展前景和发展方向
  17. 暗黑恐怖类2D游戏地牢地图素材
  18. 清新简约教育培训汇报总结PPT-朴尔PPT
  19. 关于cnn在语音识别、环境音识别中的实际运用问题
  20. Python爬虫小实践:获取某个网站所有的外部链接以及内部链接

热门文章

  1. 13 【操作mysql数据库】
  2. JavaScript的学习8——underscore
  3. Extract High-frequency Data via PC SAS
  4. 玫瑰花的python程序代码_python玫瑰花代码讲解,怎样用程序编写编写玫瑰花的代码,c程序或gava或者python...
  5. fluid 如何获取特定层的参数
  6. VMware workstation的三种网络模式
  7. python实现一个简单的http服务器
  8. ssm培训课程管理系统的微信小程序
  9. 云服务器可以用来做什么?
  10. java找出命题p和q的合取_从键盘输入两个命题变元p和q的真值-求它们的合取、析取、蕴含和等价的真值...