抽象基类与接口,共性与个性的选择!

C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在如何在恰当的场景选择恰当的继承机制是我们在设计中经常会遇到的问题,我们先来对比两者之间的区别与联系。

相同点

  • 都可以被继承。
  • 本身都不能被实例化

不同点

  • 抽象类是一个不完整的类,需要进一步细化;而接口只是一个行为上的规范。
  • 抽象基类不能实现多继承,而接口可以实现多继承。
  • 抽象基类可以定义字段、属性、包含有实现的方法。接口可以定义字段、索引器、事件但不能定义字段和包含实现的方法。

共性、个性与选择

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

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

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

设计为:

 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     }

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

  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. 当在共性较多的对象间寻求功能上的差异时,使用抽象基类。

转载于:https://www.cnblogs.com/wenghaowen/archive/2012/10/18/2729017.html

【转】抽象基类与接口,共性与个性的选择!相关推荐

  1. 抽象基类与接口,共性与个性的选择!

    抽象基类与接口,共性与个性的选择! C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在 ...

  2. 抽象基类与接口,共性与个性的选择!(区别)

    C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在如何在恰当的场景选择恰当的继承机制是 ...

  3. [转]抽象基类与接口,共性与个性的选择!

    [url]http://www.cnblogs.com/shenfx318/archive/2007/01/25/630760.html[/url] C#中的抽象基类(Abstract Class)和 ...

  4. 抽象基类与接口,共性与个性的选择

    C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在如何在恰当的场景选择恰当的继承机制是 ...

  5. python类方法和实例方法syntax errors_《Fluent Python》CH.11_面向对象_接口:从协议到抽象基类...

    主要内容 首先,本章说明抽象基类的常见用途:实现接口时作为超类使用 说明抽象基类如何检查具体子类是否符合接口定义,以及如何使 用注册机制声明一个类实现了某个接口,而不进行子类化操作 最后, 说明如何让 ...

  6. Python学习笔记28:从协议到抽象基类

    Python学习笔记28:从协议到抽象基类 今后本系列笔记的示例代码都将存放在Github项目:https://github.com/icexmoon/python-learning-notes 在P ...

  7. [python进阶]11接口:从协议到抽象基类

    本章讨论的话题是接口:从鸭子类型的代表特征动态协议,到使接口更明确.能验证实现是否符合规定的抽象基类(Abstract Base Class,ABC). 首先,本章说明抽象基类的常见用途:实现接口时作 ...

  8. [C++] - 纯虚函数 抽象基类 接口类

    翻译自:https://www.learncpp.com/cpp-tutorial/126-pure-virtual-functions-abstract-base-classes-and-inter ...

  9. C++ day24 继承(四)抽象基类,纯虚函数,protected

    文章目录 关键字protected(带来方便同时带来危险,最好不用) 抽象基类和纯虚函数(is-a关系用公有继承实现有时候也不太合适) 用圆和椭圆的笨拙派生为例,挑拨is-a和公有继承的搭档关系 替代 ...

最新文章

  1. hive sql练习_SQL语句+语法 I 数据分析面试必备
  2. Matlab与线性代数 -- 显示格式的设置
  3. bigapple之utils-update部分apk自动下载安装
  4. 成功解决TypeError: fit_transform() takes 2 positional arguments but 3 were given
  5. python 英语分词_Python英文文本分词(无空格)模块wordninja的使用实例
  6. c语言编fermat素数检验,记信安实验(一):Fermat 素性检验算法
  7. 容器入门(1) - 安装和使用Docker Registry
  8. 微信公众号从入门到入坑
  9. 《从零开始学Swift》学习笔记(Day 63)——Cocoa Touch设计模式及应用之单例模式...
  10. UTD2202C示波器如何显示峰峰值
  11. android判断图片是否模糊,Android 图片模糊 性能总结
  12. 我进滑雪场前做的功课
  13. 深度篇——实例分割(三) 细说 mask rcnn 实例分割代码 训练自己数据 之 相关网络,数据处理,工具等
  14. Knockout.js----使用计算属性(Computed Observable)
  15. 英语中表示同意或肯定的词
  16. python 字符串方法总结
  17. 单例模式( Single Pattern ): 不仅仅是回字的四种写法
  18. 淘宝代购系统|代购网站建设|代购系统开发代码对接教程
  19. Azure Kinect 使用记录 (二)
  20. SVG 画正六边形的进度条~奇奇怪怪的需求

热门文章

  1. obs多推流地址_如何用OBS将腾讯会议推流到一直播上进行直播
  2. 【JZOJ 5776】【NOIP2008模拟】小x游世界树 (树)
  3. 《海洋测绘》:从地方坐标系到2000国家大地坐标系的转换方法
  4. Java基础--数组的认识(通透!!!)
  5. Ol3中Map事件全解析
  6. iMac恢复出厂设置及安装
  7. ipad的文件连接云服务器,ipad原来可以这样用(八):文件共享——也说说云端技术...
  8. 【Vue基础七】--- 组件和模块概念
  9. 炫龙T50热键功能键
  10. 软件系统分析与设计 第七节 第八节 制表符