浪迹福州

学习.net有一段时间,目前仍在学习中

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  7 随笔 :: 0 文章 :: 88 评论 :: 0 引用

    java和c#都不支持类的多继承,相对c++来说,又都增加了接口的概念,一个类可以实现多个接口;和c++一样,java和c#保留了抽象类的概念。在编码中很多情况下接口和抽象类可以互换,并且都能正确编译和运行,GOF23种设计模式在不同的书籍上也出现了接口和抽象类混用的情况。从语言层面讲,把接口看成是仅包含抽象属性和抽象方法的抽象类,勉强可以说得过去。所以很多程序员分不清什么时候该用接口,什么时候该用抽象类,只好任选其一。

    首先,java和c#不支持类的多继承是很有道理的(类的单一职责原则),当你在设计时遇到必须用多继承的情景时,请检查你的类结构设计是否合理,或者把某些父类改成接口。

    其次,接口中声明的成员方法不能有任何实现,这样如果两个类实现这个接口,有可能两个类需要编写同样的实现。而用抽象类则可以把实现写在抽象的父类中。

    以上两点仅仅是语言层面上的区别,是显而易见的。如果做到良好的面向对象设计,把类和类关系定的合理,可能根本遇不到上述两种情况。我们来看一个场景:

    固定翼飞机、军用固定翼飞机、民用固定翼飞机(民航客机)、孙悟空、海鸥

    军用固定翼飞机、民用固定翼飞机,都属于固定翼飞机,有强烈的 is a 关系,所以应该从固定翼飞机继承;如果一架飞机是固定翼飞机,那么它不可能仅仅是固定翼飞机,因为它不是民用就是军用,所以固定翼飞机是抽象的,不会有它本身的实例,有的只是它子类的实例。所以固定翼飞机是 abstract class 。

    上述五类事物都会飞,但显然,飞机、鸟、会飞的人完全不是一回事,不应该让它们继承于一个抽象的AbstractFly类,所以固定翼飞机、孙悟空、海鸥都可以实现IFly接口,却不能从同一个抽象类继承。孙悟空实现了IFly接口,同时还可以和猪八戒等实现IChangeSelf(会变)接口。

    一个类可以实现多个接口,接口是没有实际意义的,所以即使一个类实现了再多接口,它还可以不违反类的单一职责原则。反之,继承于多个抽象类,大多会违反类的单一职责原则,要不然就是那几个抽象类设计的不合理。

    另外,根据依赖倒置原则,当高层模块和底层模块不得不耦合时,最好由高层模块定义一个“规范”,让低层模块来实现,而不是高层模块直接调用低层模块的类和成员方法。“规范”在很多时候用接口和抽象类都可以编译和运行,但通过前文的例子,我们很容易知道这时应该用接口,因为高层模块仅仅是定义了一个规范,没有实际意义,而且高层模块并不了解低层模块的类结构,不该强行为低层模块设置父类,影响低层模块实现的灵活性。

posted on 2008-09-26 15:31 浪迹福州 阅读(2045) 评论(26)  编辑 收藏 网摘 所属分类: 2、面向对象软件设计5、杂谈

评论

你理解的很不错了
类的多继承还是有用的 在GoF中有个很明显的例子 观察者模式中的observer和subject用C++可以抽象出来 而用C#和Java就只能定义2个接口了

  回复  引用    

#2楼 2008-09-26 16:17 kkun      
是否可以理解为,
功能设计为接口
具有相同或相似特征的事物设计为虚类,


  回复  引用  查看    

#3楼 2008-09-26 16:20 xiao_p      
从语法角度讲 , abstract class 和 interface 根本没有什么区别

接口就是一个 强制成员 为 public 的 且没有实现的 抽象类

  回复  引用  查看    

浪在福州哪个地方?
  回复  引用    

接口是解决“能做什么”的问题
抽象类是解决“是什么”的问题

  回复  引用    

#6楼 2008-09-26 16:42 执手麦田      
这是一种很好的理解方式。抽象类其实就是不能用的模板,一个理论而已,呵呵。
  回复  引用  查看    

#7楼 2008-09-26 16:50 Kai.Ma      
什么场合用接口还是抽象类,取决于Achitec对当时场合的理解。
如果理解成is a,用抽象类;反之like a,用接口。

接口是一种松耦合策略,抽象类属于紧耦合策略。

  回复  引用  查看    

#8楼 2008-09-26 17:01 jetable[未注册用户]
写得太好了,理解的很清晰,给了我很多指点,感谢
  回复  引用    

#9楼 2008-09-26 17:04 newos      
觉得那个例子举的不是太好
  回复  引用  查看    

#10楼 2008-09-26 17:21 kkun      
--引用--------------------------------------------------
nonamename: 接口是解决“能做什么”的问题
抽象类是解决“是什么”的问题
--------------------------------------------------------
精辟

  回复  引用  查看    

#11楼 2008-09-26 17:24       
学习了
  回复  引用  查看    

其实C#还有Virtual虚方法。我们也可以继承一个普通类,然后override它的虚方法。类似实现抽象类的abstract方法。而父类也可以有自己真实的方法,但它可以不是抽象类,因此可以new一个实例。而且还可以调用父类的Virtual方法。比如我们在WinForm下一般继承Form类(非抽象),可以重写Onload方法。对于父类的一般方法,可以用new来强制覆盖。
  回复  引用  查看    

#13楼 2008-09-26 23:01 canbeing      
看了有不小收获,谢谢 。
  回复  引用  查看    

#14楼 2008-09-26 23:22 浪尘      
个人认为,少用接口的多继承会让条理比较清晰,有时,继承可以用组合来替换会达到比较好的松耦效果,并能较好的遵守开-闭原则
  回复  引用  查看    

#15楼 2008-09-27 04:03 梁逸晨      
我一向来是分不清什么时候用接口什么时候用抽象类,但是看了这篇帖子,我的心立刻受到震撼了。楼主是前无古人后无来者的CodingKing!
这篇文章主线分明,引人入胜,平淡中显示出不凡的文学功底,可谓是字字珠玑,句句经典,是我辈应当学习之典范。正所谓:“一马奔腾,射雕引弓,天地都在我心中!”

  回复  引用  查看    

#16楼 2008-09-27 09:07 Tony Zhou      
--引用--------------------------------------------------
梁逸晨: 我一向来是分不清什么时候用接口什么时候用抽象类,但是看了这篇帖子,我的心立刻受到震撼了。楼主是前无古人后无来者的CodingKing!
这篇文章主线分明,引人入胜,平淡中显示出不凡的文学功底,可谓是字字珠玑,句句经典,是我辈应当学习之典范。正所谓:“一马奔腾,射雕引弓,天地都在我心中!”
--------------------------------------------------------

  回复  引用  查看    

#17楼 2008-09-27 09:22 二叉树      
--引用--------------------------------------------------
梁逸晨: 我一向来是分不清什么时候用接口什么时候用抽象类,但是看了这篇帖子,我的心立刻受到震撼了。楼主是前无古人后无来者的CodingKing!
这篇文章主线分明,引人入胜,平淡中显示出不凡的文学功底,可谓是字字珠玑,句句经典,是我辈应当学习之典范。正所谓:“一马奔腾,射雕引弓,天地都在我心中!”
--------------------------------------------------------
由衷的佩服这位兄弟的文学功底。

  回复  引用  查看    

#18楼 2008-09-27 09:23 二叉树      
--引用--------------------------------------------------
Kai.Ma: 什么场合用接口还是抽象类,取决于Achitec对当时场合的理解。
如果理解成is a,用抽象类;反之like a,用接口。

接口是一种松耦合策略,抽象类属于紧耦合策略。
--------------------------------------------------------
--引用--------------------------------------------------
kkun: --引用--------------------------------------------------
nonamename: 接口是解决“能做什么”的问题
抽象类是解决“是什么”的问题
--------------------------------------------------------

受益

  回复  引用  查看    

#19楼 2008-09-27 10:05 iMax Shi      
接口 体现 like a 的关系;抽象类 体现 is a 的关系
  回复  引用  查看    

#20楼 2008-09-27 10:30 tsyung      
一句话概括:接口定义行为,抽象类定义职责。
在lz的文章中提到,飞机、鸟、会飞的人都有一种行为,就是飞,而从另外角度来看,他们完全完全不是一回事,各有各的职责。所以通俗的理解为:接口定义的是动作,抽象类定义的是属性和成员。

  回复  引用  查看    

#21楼 2008-09-27 11:51 张挚      
讲的很精辟~受益了.多谢博主!
  回复  引用  查看    

#22楼 2008-09-27 20:01 ViCross      
好东西.
我觉得:
抽象对象是面向属性的,
而接口是面向功能的

  回复  引用  查看    

#23楼[楼主] 2008-09-28 14:59 浪迹福州      
多谢大家的评论和支持!从评论中我也学到很多
  回复  引用  查看    

#24楼[楼主] 2008-09-28 15:00 浪迹福州      
--引用--------------------------------------------------
稍微软一点了: 浪在福州哪个地方?
--------------------------------------------------------
既然是浪,就浪哪儿是哪儿了

  回复  引用  查看    

#25楼[楼主] 2008-09-28 15:02 浪迹福州      
--引用--------------------------------------------------
梁逸晨: 我一向来是分不清什么时候用接口什么时候用抽象类,但是看了这篇帖子,我的心立刻受到震撼了。楼主是前无古人后无来者的CodingKing!
这篇文章主线分明,引人入胜,平淡中显示出不凡的文学功底,可谓是字字珠玑,句句经典,是我辈应当学习之典范。正所谓:“一马奔腾,射雕引弓,天地都在我心中!”
--------------------------------------------------------
我对阁下的文采之敬仰犹如滔滔江水,连绵不绝!

  回复  引用  查看    

#26楼 2008-10-23 02:59 tianhu      
讲解的非常好。
  回复  引用  查看    

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1299615




相关文章:

相关链接: