继承:复用接口

来源:互联网 发布:office办公软件自学 编辑:程序博客网 时间:2024/06/06 03:04
对象这种观念,本身就是十分方便的工具,使得你可以通过概念(concept)将数据和功能
封装到一起,因此你可以对问题域的观念给出恰当的表示,而不用受制于必须使用底层机器
语言。这些概念用关键字 class 来表示,形成了编程语言中的基本单位。
遗憾的是,这样做还是有很多麻烦,在创建了一个类之后,即使另一个新类与其具有相似的
功能,你还是得重新创建一个新类。如果我们能够以现有的类为基础,复制它,然后通过添
加和修改这个副本来创建新类那就要好得多了。通过继承便可以达到这样的效果,不过也有
例外,当源类(被称为基类( base class)、超类(super class)或父类(parent class))发生变动时,
被修改的“副本”(被称为导出类(derived class)、继承类(inherited class)或子类(subclass, child
class))也会反映出这些变动。
类型不仅仅只是描述了作用于一个对象集合之上的约束条件,同时还有与其它类型之间的关
系。两个类型可以有相同的特性和行为,但是其中一个类型可能比另一个含有更多的特性,
并且可以处理更多的消息(或以不同的方式来处理消息)。继承使用基类和导出类的概念表
示了这种类型之间的相似性。一个基类包含其所有导出类共享的特性和行为。你可以创建一
个基类来表示系统中某些对象的核心概念,从基类中导出其它的类,来表示此核心可以被实
现的各种不同方式。
以垃圾回收机(trash-recycling machine)为例,它用来归类散落的垃圾。trash 是基类,每一
件垃圾都有重量、价值等特性,可以被切碎、熔化或分解。在此基础上,可以通过添加额外
的特性(例如瓶子有颜色)或行为(例如铝罐可以被压碎,铁罐可以被磁化)导出更具体的
垃圾类型。此外,某些行为可能不同(例如纸的价值依赖其类型和状态)。你可以通过使用
继承来构建一个类型层次结构(type hierarchy)来表示你的待解问题相关联的类型。
第二个例子是经典的在计算机辅助设计系统或游戏仿真系统中可能被泳道的几何形(shape)
的例子。基类是 shape,每一个 shape 都具有尺寸、颜色、位置等,同时每一个 shape 都可
以被绘制、擦除、移动和着色等。在此基础上,可以导出(继承出)具体的几何形状——圆
形、正方形、三角形等——每一种都具有额外的特性和行为,例如某些形状可以被翻转。某
些行为可能并不相同,例如面积计算。类型层次结构同时体现了几何形状之间的相似性和相
异性。
将解决方案转换成为问题术语的描述是大有裨益的,因为你不需要在问题描述和解决方案描
述之间建立众多的中介模型。通过使用对象,类型层次结构成为了主要模型,因此,你可以
直接从真实世界中对系统进行描述过渡到用代码对系统进行描述。事实上,对使用面向对象
设计的人们来说,困难之一是从开始到结束太过于简单。对于训练有素、善于寻找复杂的解
决方案的头脑来说,可能会在一开始被这种简单性给难倒

当你继承现有类型时,也就创造了新的类型。这个新的类型不仅包括现有类型的所有成员(尽
管 private 成员被隐藏了起来,并且不可访问),而且更重要的是它复制了基类的接口。也就
是说,所有可以发送给基类对象的消息同时也可以发送出导出类。由于我们通过可发送消息
的类型可知类的类型,所以这也就意味着导出类与基类具有相同的类型。在前面的例子中,
“一个圆形也就是一个几何形状”。通过继承而产生的类型等价(type equivalence)是理解
面向对象程序设计方法内涵的重要门槛。
由于基类和导出类具有相同的基础接口,所以伴随此接口的必定有某些具体实现。也就是说,
当对象接收到特定消息时,必须有某些代码去执行。如果你只是简单地继承一个类而并不作
其他任何事,那么在基类接口中的方法将会直接继承到导出类中。这意味着导出类的对象不
仅与基类拥有相同的类型,而且还拥有相同的行为,这样做并没有什么特别的意义。

有两种方法可以使基类与导出类产生差异。第一种方法非常直接:直接在导出类中添加新方
法。这些新方法并不是基类接口的一部分。这意味着基类不能直接满足你的所有需求,因此
你必需添加更多的方法。这种对继承简单而基本的使用方式,有时对你的问题来说确实是一
种完美的解决方式。但是,你应该仔细考虑是否存在你的基类也需要这些额外方法的可能性。
这种设计的发现与迭代过程在面向对象程序设计中会经常发生。

虽然继承有时可能意味着在接口中添加新方法(尤其是在以 extends 关键字表示继承的 Java
中),但并非总需如此。第二种以及其它使导出类和基类之间产生差异的方法是改变现有基
类的方法的行为。这被称之为重载(overriding)。


要想重载某个方法,可以直接在导出类中创建该方法的新定义即可。你可以说:“此时,我
 

正在使用相同的接口方法,但是我想在新类型中做些不同的事情。”


原创粉丝点击