(或对消息进行不同的处理)。继承表示了基本类型和派生类型之间的相似性。一个基本类型具
有所有由它派生出来的类型所共有的特性和行为。程序员创建一个基本类型以描述系统中一些
对象的思想核心。由这个基本类型派生出其他类型,表达了认识该核心的不同途径。
例如,垃圾再生机要对垃圾进行分类。这里基本类型是“垃圾”, 每件垃圾有重量、价值
等等,并且可以被破碎、融化或分解。这样,可以派生出更特殊的垃圾类型,它们可以有另外
的特性(瓶子有颜色)或行为(铝可以被压碎,钢可以被磁化)。另外,有些行为可以不同
(纸的价值取决于它的种类和状态)。程序员可以用继承建立类的层次结构,在该层次结构中用
类型术语来表述他需要解决的问题。
第二个例子是经典的形体问题,可以用于计算机辅助设计系统或游戏模拟中。这里基本类
型是“形体”,每个形体有大小、颜色、位置等。每个形体能被绘制、擦除、移动、着色等。
由此,可以派生出特殊类型的形体:圆、正方形、三角形等,它们中的每一个都有另外的特性
和行为,例如,某些形体可以翻转。有些行为可以不同(计算形体的面积)。类型层次结构既
体现了形体间的类似,又体现了它们之间的区别。
用与问题相同的术语描述问题的解是非常有益的,这样,从问题描述到解的描述之间就不
需要很多中间模型(程序语言解决大型问题,就需要中间模型)。面向对象之前的语言,描述
问题的解不可避免地要用计算机术语。使用对象术语,类型层次结构是主要模型,所以可以从
现实世界中的系统描述直接进入代码中的系统描述。实际上,使用面向对象设计,人们的困难
之一是从开始到结束过于简单。一个已经习惯于寻找复杂解的、训练有素的头脑,往往会被问
题的简单性难住。
1.1.3 多态性
当处理类型层次结构时,程序员常常希望不把对象看作是某一特殊类型的成员,而把它看
作基本类型成员,这样就可以编写不依赖于特殊类型的代码。在形体例子中,函数可以对一般
形体进行操作,而不关心它们是圆、正方形还是三角形。所有的形体都能被绘制、擦除和移动,
所以这些函数能简单地发送消息给一个形体对象,而不考虑这个对象如何处理这个消息。
这样,新添类型不影响原来的代码,这是扩展面向对象程序以处理新情况的最普通的方法。
例如,可以派生出形体的一个新的子类,称为五边形,而不必修改那些处理一般形体的函数。
通过派生新子类,很容易扩展程序,这个能力很重要,因为它极大地减少了软件维护的花费。
(所谓“软件危机”正是由软件的实际花费远远超出人们的想象而产生的。)
如果试图把派生类型的对象看作它们的基本类型(圆看作形体,自行车看作车辆,鸬鹚看作
鸟),就有一个问题:如果一个函数告诉一个一般形体去绘制它自己,或者告诉一个一般的车辆去
行驶,或者告诉一只一般的鸟去飞,则编译器在编译时就不能确切地知道应当执行哪段代码。同
样的问题是,消息发送时,程序员并不想知道将执行哪段代码。绘图函数能等同地应用于圆、正
方形或三角形,对象根据它的特殊类型来执行合适的代码。如果增加一个新的子类,不用修改函
数调用,就可以执行不同的代码。编译器不能确切地知道执行哪段代码,那么它应该怎么办呢?
在面向对象的程序设计中,答案是巧妙的。编译器并不做传统意义上的函数调用。由非
O O P 编译器产生的函数调用会引起与被调用代码的“早捆绑”,对于这一术语,读者可能还没
有听说过,因为从来没有想到过它。早捆绑意味着编译器对特定的函数名产生调用,而连接器
确定调用执行代码的绝对地址。对于 O O P ,在程序运行之前,编译器不确定执行代码的地址,
所以,当消息发送给一般对象时,需要采用其他的方案。
为了解决这一问题,面向对象语言采用“晚捆绑”的思想。当给对象发送消息时,在程序
2 C + +编程思想
评论0
最新资源