惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
T
Threatpost
Latest news
Latest news
N
News | PayPal Newsroom
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Help Net Security
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
TaoSecurity Blog
TaoSecurity Blog
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
T
Threat Research - Cisco Blogs
O
OpenAI News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
The Exploit Database - CXSecurity.com
NISL@THU
NISL@THU
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Securelist
小众软件
小众软件
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
S
SegmentFault 最新的问题
Cisco Talos Blog
Cisco Talos Blog
云风的 BLOG
云风的 BLOG
AWS News Blog
AWS News Blog
GbyAI
GbyAI
N
News and Events Feed by Topic
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
美团技术团队
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
博客园 - 聂微东
V2EX - 技术
V2EX - 技术
T
Troy Hunt's Blog
SecWiki News
SecWiki News
S
Secure Thoughts
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学
腾讯CDC
H
Heimdal Security Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Privacy International News Feed

博客园 - Snow*Cao

request 生命周期及参数信息 vs2010 调试快捷键 温故而知新:封装、继承、多态 海量的jQuery插件帖,很经典 委托事件的理解(转载) 常用JQuery插件整理 关于数据挖掘的详细介绍的一些网址 DropDownList 默认展示从数据库查询的值 Python 开发环境搭建 WCF优秀资源整理--持续更新 Python入门视频教程 txt文本导入到sql server数据库 C#中值类型和引用类型 通过IIS自带工具Iisapp.vbs查询哪个站点占用资源 主键与外键 分布式缓存BeIT Memcached简介 HttpHandlers和HttpModules接口详解 ASP.NET页面运行机制 jquery跨域获取数据以及分页 - Snow*Cao - 博客园
抽象基类与接口,共性与个性的选择!(区别)
Snow*Cao · 2011-03-16 · via 博客园 - Snow*Cao

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

转载自(http://www.cnblogs.com/shenfx318/archive/2007/01/25/630760.html