开发者社区> 异步社区> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

《UML面向对象设计基础》—第1章1.7节继承

简介:
+关注继续查看

本节书摘来自异步社区《UML面向对象设计基础》一书中的第1章1.7节继承,作者【美】Meliir Page-Jones,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.7 继承
UML面向对象设计基础
如果你写了一个类C,后来又发现一个类D 除一些额外的属性和操作外与类C几乎是一样的,你会怎么办呢?一种办法是简单地复制C的所有属性和操作,然后将其放到D中。但这种方法不仅增加了额外的工作,而且复制本身也存在维护的麻烦。更好的方法是让类D向类C“请求使用其操作”,这种方法称为继承(inheritance)。

继承(从C到D)是指类D在类C中隐式地定义其每个属性和操作,就好象

这些属性和操作是在类D本身中定义一样。

C称为D的超类。D称为C的子类。

换言之,通过继承,类D的对象可以充分利用类C对象的属性和操作 。

继承代表着面向对象与传统系统方法区别的另一个主要方面。使你可以更加有效地构造软件:

首先,构造类以便处理一般情况。
然后,为处理特殊情况,增加更特殊的类继承首批建立的类。这些新类就可以使用原来类的所有操作和属性(包括类和实例的操作和属性)。
下面的例子有助于说明上述原理。假设在航空应用中有一个类Aircraft。Aircraft可以定义名为turn的实例操作,实例属性名为course。

类Aircraft处理与任何种类的飞行器有关的活动或信息。然而一些特殊的飞行器执行特殊的活动,因此需要特殊的信息。例如,滑翔机执行特殊的活动(如释放拖链)可能需要记录特殊的信息(如是否连接拖链)。

因此,我们可以定义另一个类Glider,使其继承Aircraft。Glider有一个名为release Towline的实例操作和一个名为WeatherTowlineAttached的实例属性(属于类Boolean)。图1.7给出了结构图,空心箭头表示继承。

现在让我们来设想一段面向对象程序的继承机制,首先从类Aircraft和Glider生成对象,然后给这些对象发送消息。在这段程序后面讨论了标记为从(1)到(4)的四条语句。

var ac:Aircraft:= Aircraft.New ;

var gl:Glider:=Glider.New;

…

ac.turn(newCourse,out turnOK);   (1)

gl.releaseTowline;           (2)

gl.turn(newCourse,out turnOK);   (3)

ac.releaseTowline;(4)


3d414ba827f2f752b8ba714d69cb8666e3427589

① ac表示由ac指定的对象接收消息 turn(newCourse,out turnOK) ,执行操作turn (带有适当参数)。因为ac是Aircraft的一个实例,ac将直接使用在类Aircraft中已经定义的操作turn。

② gl表示由gl指定的对象接收消息releaseTowline,执行操作releaseTowline(不需要参数)。
  因为gl是Glider的一个实例,gl将直接使用在类Glider中已经定义的操作releaseTowline。

③ gl表示由gl指定的对象接收消息turn(newCourse,out turnOK),执行操作turn(带有适当参数)。如果没有定义继承,这个消息在执行时会出错(如无定义操作-turn),因为gl是Glider的实例,而Glider中没有名为turn的操作。
  然而,由于Aircraft是Glider的超类,对象gl也被允许使用Aircraft的任何操作。如果Aircraft有一个超类FlyingThing,gl将被允许使用FlyingThing的任何操作。因此,标记为(3)的代码行可以正确运行,在Aircraft中定义的操作turn也会被执行。

④ 这行代码不会执行!ac为Aircraft的实例,没有定义名为releaseTowline 的操作。继承在这里用不上,只有Glider类定义了releaseTowline操作,并且Glider是Aircraft的子类。由于从Glider 到Aircraft方向没有继承,系统将由于错误而停止运行。这样设计是合理的,因为ac可能表示大型喷气式飞机,操作releaseTowline对其没有意义。

在1.6节讨论了类和对象的区别。现在我们知道对象和实例之间也存在细微的差别。尽管目前为止我们将“对象”和“实例”几乎同样对待,在某种意义上继承允许一个对象同时是多个类的实例。

在现实世界中也是如此。如果你拥有一个滑翔机,当然完全拥有一个尾部具有标识(句柄)的对象。这架滑翔机(显然)是滑翔机的一个例子,同时也是飞行器的例子。概念上讲,你拥有的这个对象是Glider的实例,也是Aircraft的实例。

  实际上,上述例子说明了一个有效使用继承的有效测试。如果可以说“某个D是某个C”,则D差不多就是C的子类。因此,既然可以说“滑翔机是某种飞行器”,则类Glider应该是类Aircraft(飞行器)的子类,在第10、11和12章将进一步讨论继承的正确使用方法。

让我们进一步探讨继承。gl表示由gl引用的对象在运行时是两部分的融合。一部分是为Glider定义的实例操作和实例属性;另一部分是为Aircraft定义的实例操作和实例属性。如图1.18所示。

在大多数语言中,继承子类继承超类所提供的一切信息;子类不能有选择地继承。但可以通过技巧使子类略去继承的操作,这将在第1.8节讨论。


34ba48d45b227a647000bfd5582bcb4d9e0907c2

采用好的面向对象语言实现继承的实际代码非常直观。只需声明每个子类继承哪个超类。例如:
class Glider inherits from Aircraft;

…

这个继承的例子为单继承,指每个类至多有一个直接超类。此外,还有多继承的情形。多继承指每个类可以有任意多个直接超类。

多继承能将单继承的继承树转换为继承框架,如图1.19所示。


dcd822604398977e4fb7f9035454615737e5de4a

多继承引入了一些设计上的难题,因为子类从多个父辈继承,可能引起继承操作或属性的冲突。冲突的操作具有相同的名字,继承子类不能容易地表述继承的是哪个操作。

诸如命名冲突问题影响了多继承的声誉。多年来,对多继承的谴责和赞成已经到了炙热化的程度。我声明我是赞同多继承的,因为现实中需要频繁使用多继承的子类。正如图1.19所示,类PassengerAircraft合理地从类Aircraft和类PessengerVehicle获得继承。

因为多继承可能建立复杂和难以理解的结构,因此,使用多继承比使用单继承要更加慎重。目前为止,C++和Eiffel两个主要语言支持多继承,而另外两个主要语言Java和Smalltalk则不支持多继承。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
《设计模式解析(第2版•修订版)》—第1章 1.7节面向对象程序设计实践
对象对自己行为所负的责任越多,控制程序需要负的责任就越少。封装使对象内部行为的变化对其他对象变得透明了。封装有助于防止不良副作用。
1420 0
《设计模式解析(第2版•修订版)》—第1章 1.2节面向对象范型之前:功能分解
让我们从对一种常用的软件开发方法的考察开始吧。如果给你一个任务,要编写一段代码,访问在数据库中存储的形状描述然后显示出来。按照所需要的步骤来思考,是一种很自然的选择。
1185 0
《设计模式解析(第2版•修订版)》—第1章 1.8节特殊对象方法
所有面向对象语言都会在对象删除时查找并执行相应的析构函数。与构造函数一样,析构函数的使用也是对象“自己负责自己”所要求的。
1223 0
《面向对象设计实践指南:Ruby语言描述》—第1章 1.1节设计赞歌
世界是过程式的。时间不停在向前流动,而事件也一个接一个地逝去。你每天早上的过程或许就是:起床、刷牙、煮咖啡、穿衣,然后上班。这些活动都可以使用过程软件来建模。因为了解事件的顺序,所以你可以编写代码来完成每一件事情,然后仔细地将这些事情一个接一个地串在一起。
1603 0
+关注
异步社区
异步社区(www.epubit.com)是人民邮电出版社旗下IT专业图书旗舰社区,也是国内领先的IT专业图书社区,致力于优质学习内容的出版和分享,实现了纸书电子书的同步上架,于2015年8月上线运营。公众号【异步图书】,每日赠送异步新书。
12049
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载