面向对象设计之五 继承与多态的危险性

继承与多态的危险性

继承与多态使面向对象的设计方法与传统的软件开发方式区别开来。然而滥用继承也会将一些设计方案带入无法实现的地步。

1 继承的滥用

本节的目标是审查不同形式的错误的继承,以避免在将用的工程项目中滥用继承。

1.1 组合与继承混用

混淆了is-a与has-a的关系,使用继承将整体的多个部分整合在一起。

例如一架飞机是由机身、机翼、引擎等各部分组合的,而错误的将飞机继承自机身、机翼、引擎。这样在理解上就变成了,飞机同时是一种机身、一种机翼、一种引擎,这种理解当然是错误的。

 

1.2 继承层次倒置

在对某些复杂的现实情况抽象模型时,混淆了一般和特殊,导致类型层次倒置。

例如在现实中,企业组织是雇员向经理负责,经理向董事会成员负责。如果以抽象时以这种组织层次关系来建立类的抽象层次,则会出现继承层次倒置,例如经理派生自董事,而员工派生自经理。

 

1.3 混淆类与其实例

观看下面的示例:

观察熊与熊猫的实例为单个动物,而濒危动物的实例则是所有特种,因此这样继承下来之后则熊猫的实例也是濒危动物的实例,熊猫盼盼代表了所有的濒危特种,从is-a的角度并不合适。正确的表示方法为下面的类图:

动物中包括了一个引用,指向一个特种实例的引用,熊猫和熊在初始化时将初始化各自合适的物种的实例,指向濒危或非濒危的实例。


1.4 误用

现在有一个立方体的类,其实现了计算体积的方法,现在有一个房间类(room),为了利用计算体积的方法,房间类继承了立方体。但立方体的其他方法在房间上应用则是非法的,例如立方体的旋转。同时从is-a的角度上来说,房间是一个立方体的实例,这与常理上也说不通,正确的说法是房间的空间形状是立方体的。表示这种说法的类图如下图所示:

这种使用另一类中代码的技术叫做消息转发(或者委托),这种基于消息转发的设计方法,可以用来替代继承,但它并不使我们获得所有继承而来的操作,而要求我们逐条消息的指定需求访问其它类别的操作或属性。


2 多态的危险性

多态的引入提高了面向对象设计的简洁性,它允许多个类使用相同的名字来定义一个操作,也允许一个变量访问多个类中的对象。因此多态性实际是让操作环境自动选择相应的操作来执行,而无需复杂的case语句。操作和变量均可能表现出性。


2.1 操作的多态性

操作op的多态区是定义了op操作的类的集合。如果类A及其继承类都实现了op,且这些类构成了整个继承层次图的一个分支的多态区,称其为一个多态锥,A为多态锥的顶点。继承层次实现的也可能是一个不完整多态锥,因为某些类中没有定义op操作。

 

2.2 变量的多态性

变量的多态性是指变量在不同时间可以指向不同类的对象。变量V的多态区是V指向的对象所属类的集合。

例如在Java中基类对象可以引用不同的派生类的对象,而在python这种动态类型中一个变量可以随时指向任何一个类型。

 

2.3 消息中的多态性

消息需要指明消息的对象obj及执行的操作op,可以用obj.op表示。如前两节所描述,操作和变量都具有多态区。如果设计的系统中,变量的多态区包含于操作的多态区中,则系统是安全的。反之,如果对象多态落在操作多态之外,则执行时就会出现问题。

 

2.4 多态性与一般性

一般性也称谓参数化类或模板,参数化类也可能由于多态区冲突而引起运行时错误。可以这么说,在一般性的多态区,任何实例化的类都需要支持一般化多态区中的操作,否则就会出现运行时错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值