C#中的抽象基类(Abstract Class)和接口(Interface)都实现了面向对象中的继承机制,它们通过定义抽象方法匀实现了对继承类的功能上的约束,那么在如何在恰当的场景选择恰当的继承机制是我们在设计中经常会遇到的问题,我们先来对比两者之间的区别与联系。  相同点  都可以被继承。  本身都不能被实例化  不同点  抽象类是一个不完整的类,需要进一步细化;而接口只是一个行为上的规范。  抽象基类不能实现多继承,而接口可以实现多继承。  抽象基类可以定义字段、属性、包含有实现的方法。接口可以定义字段、索引器、事件但不能定义字段和包含实现的方法。      共性、个性与选择  有的书上写到C#中推荐使用接口(Interface)来替代抽象基类(Abstract Class),并强调使用接口的诸多好处,这点我不敢苟同,从上面列表中看来,两者之间还是存在不少差异的,而这种差异的存在性必然决定了适用场景的不同,例如在抽象基类中可以为部分方法提供默认的实现,从而避免在子类中重复实现它们,提高代码的可重用性,这是抽象类的优势所在;而接口中只能包含抽象方法。至于何时使用抽象基类何时使用接口关键还是取决于用户是如何看待继承类之间的联系的,用户更加关心的是它们之间的个性差异还是它们之间的共性联系。举个生活中的例子加以说明。  如果给你三个对象分别是人、鱼、青蛙,让你为他们设计个基类来概括它们之间的联系,那么首先给你的感觉肯定是它们个体间的差异性较大,很难抽象出共性,然而若让你概括他们行为之间的共性,你可能想了想会意识到他们都会游泳,只不过是游泳方式迥异。那么这时你就应当考虑使用接口而不是抽象基类,原因有三条:  个性大于共性。  差异较大的个性间具有某些相同的行为。  相同行为的实现方式有较大区别。  设计为: 好,这时再给你三个对象,分别是鲫鱼、鲤鱼、金鱼,仍然让你设计基类来概括它们之间的联系,那么你第一个意识到的肯定是它们都属于鱼类,其次是他们游泳的方式可能稍有差异,这时就应当使用抽象基类而不是接口,对比着上面的例子,原因也有三条:  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       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 .类是对对象的抽象,可以把抽象类理解为把类当作对象,抽象成的类     接口只是一个行为的规范或规定,微软的自定义接口总是后带able字段,证明其是表述一类类“我能做。。。”抽象类更多的是定义在一系列紧密相关的类间,而接口大多数是关系疏松但都实现某一功能的类中     2 .接口基本上不具备继承的任何具体特点,它仅仅承诺了能够调用的方法;      3 .一个类一次可以实现若干个接口,但是只能扩展一个父类      4 .接口可以用于支持回调,而继承并不具备这个特点.      5 .抽象类不能被密封。     6 .抽象类实现的具体方法默认为虚的,但实现接口的类中的接口方法却默认为非虚的,当然您也可以声明为虚的。   7 .(接口)与非抽象类类似,抽象类也必须为在该类的基类列表中列出的接口的所有成员提供它自己的实现。但是,允许抽象类将接口方法映射到抽象方法上。     8 .抽象类实现了oop中的一个原则,把可变的与不可变的分离。抽象类和接口就是定义为不可变的,而把可变的座位子类去实现。     9 .好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。     10 .尽量避免使用继承来实现组建功能,而是使用黑箱复用,即对象组合。因为继承的层次增多,造成最直接的后果就是当你调用这个类群中某一类,就必须把他们全部加载到栈中!后果可想而知.     11 .如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法      如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。       如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。 --------------------------------------------------------------------- 抽象类:   a.包含一个或多个抽象方法或属性的类必须定义为抽象类    b.继承抽象类的派生类必须实现抽象类的所有抽象方法或属性,否則該派生类也必是抽象类,至到完全实现为止.    c.抽象类必须是公共的( public ).    d.抽象类不存在对象实例,但可以申明引用变量.另外抽象类中可以有非抽象方法,供派生类调用.  接 口:    1 .接口中定义抽象的方法,属性,索引,事件     2 .接口必须由类來实现,故其只能是默认public的,不可顯式申明,不能申明为  static      3 .实现接口的类必须完全实现接口中的所有的方法属性,索引,事件,不能只实现一部分     4 .一个类只能继承一个基类,但可以实现多个接口,其中继承的基类必须放在最前面,然后是接口,它們用逗號分開.  ----------------------------- 何时用抽象类,何时用接口? ※ 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。 ※ 如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。 ※ 如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。 ※ 如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。 --------------------------------- 1 、接口中只能有方法,不能有字段;抽象类中即可以有方法,也可以有属性和字段;  2 、接口中的方法不需要实现,而抽象类中可以有实现了的方法;  3 、接口在一定程度上可以代替多继承。  4 、实现接口,也就意味着必须实现接口中的所有方法。如果继承抽象类的子类还是抽象类,则可以只实现部分方法。  5 、接口和抽象类都不被实例化成对象。 ----------------------------------- 首先要明确抽象类和接口使用上的区别,类只能单一的继承,如果一个类的方法只让其派生类实现,那么就可以用抽象类,如果方法是被多个类使用,那么就使用接口。  例如:   使用抽象类:    abstract   class  A   {     abstract   public   void  put();   }    class  B : A   {     public   void  put()    {      Console.WriteLine( " B " );    }   }    // -----------------------------------------   使用接口:    interface  Ia   {     public   void  put();   }      class  A : Ia   {     public   void  put()    {      Console.WriteLine( " A " );    }   }      class  B : Ia   {     public   void  put()    {      Console.WriteLine( " B " );    }    }

posted on 2007-08-06 17:31 寸芒 阅读(66) 评论(3)  编辑 收藏

#1楼[楼主]   回复  引用  查看

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

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

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

  2. 【转】抽象基类与接口,共性与个性的选择!

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

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

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

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

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

  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. 总结一下“网络连接受限制”无法上网的解决办法
  2. Promise从入门到精通
  3. 输出超限怎么解决 oj_三菱PLC输出指示灯输出模块不亮怎么解决
  4. poj1961Period(next数组)
  5. 蓝桥杯C++ AB组辅导课 第六讲 双指针、BFS与图论 Acwing
  6. 到底要不要拯救地球?真·逻辑鬼才!| 今日最佳
  7. 使用sp_executesql存储过程执行动态SQL查询
  8. (初学者)初学者的编程的苦恼
  9. win7桌面工具无法连接服务器,小编为你讲讲win7系统桌面天气小工具提示无法连接服务的解决方案...
  10. Structs1.0入门知识
  11. 免费领,单片机入门到高级进阶学习攻略(附教程+工具)
  12. auto CAD 常用快捷键指令
  13. linux输入中文老是有字母,Fcitx 中文输入法中世界语字母的输入方法
  14. springboot毕设项目商城积分兑换系统pez18(java+VUE+Mybatis+Maven+Mysql)
  15. MSP430通过IAR下载时出现的Failed to load debugee: C:\XX\XXIAR\Release\Exe\Wireless measurement.txt无法下载程序的问题
  16. Java文件路径问题
  17. 跟ChatGPT,聊聊ChatGPT
  18. 手把手教你通过端口映射,轻松搭建Windows远程桌面
  19. 一点英语不会可以学java吗_不会英语能学编程吗 编程好不好学
  20. ASP.NET人事管理系统课程设计

热门文章

  1. 黄油刀 Butterknife的使用准备工作
  2. python可视化图表和excel的区别_Excel的数据可视化和Python的有什么不同?
  3. 华为机试真题 C++ 实现【最大化控制资源成本】【100%通过率】【2022.11 Q4 新题】
  4. 测试工程师面试一般常用问题
  5. 【Spring】Bean的实例化过程
  6. 云班课计算机第二阶段测试卷,云班课测试自动答案
  7. 云计算技术架构-云计算四种模式(公有云、私有云、混合云、行业云)
  8. bpmn-js汉化(将元素提示语进行汉化)
  9. android 重启 logo,MSM8909+Android5.1.1开机logo对应的splash.img生成
  10. 四, Scala 伴生对象, 特质