所以,我们一般创建一个特定的对象(
Circle
,
Square
,或者
Triangle
),把它
上溯造型到一个
Shape
(忽略对象的特殊类型),以后便在程序的剩余部分使用
匿名
Shape
句柄。
作为对多形性和上溯造型的一个简要回顾,可以象下面这样为上述例子编码
(若执行这个程序时出现困难,请参考第
3
章
3.1.2
小节“赋值”):
516-517
页程序
基础类可编码成一个
interface
(接口)、一个
abstract
(抽象)类或者一个普
通类。由于
Shape
没有真正的成员(亦即有定义的成员),而且并不在意我们创
建了一个纯粹的
Shape
对象,所以最适合和最灵活的表达方式便是用一个接口。
而且由于不必设置所有那些
abstract
关键字,所以整个代码也显得更为清爽。
每个衍生类都覆盖了基础类
draw
方法,所以具有不同的行为。在
main()
中
创建了特定类型的
Shape
,然后将其添加到一个
Vector
。这里正是上溯造型发生
的地方,因为
Vector
只容纳了对象。由于
Java
中的所有东西(除基本数据类型
外)都是对象,所以
Vector
也能容纳
Shape
对象。但在上溯造型至
Object
的过
程中,任何特殊的信息都会丢失,其中甚至包括对象是几何形状这一事实。对
Vector
来说,它们只是
Object
。
用
nextElement()
将一个元素从
Vector
提取出来的时候,情况变得稍微有些复
杂。由于
Vector
只容纳
Object
,所以
nextElement()
会自然地产生一个
Object
句
柄。但我们知道它实际是个
Shape
句柄,而且希望将
Shape
消息发给那个对象。
所以需要用传统的
"(Shape)"
方式造型成一个
Shape
。这是
RTTI
最基本的形式,
因为在
Java
中,所有造型都会在运行期间得到检查,以确保其正确性。那正是
RTTI
的意义所在:在运行期,对象的类型会得到鉴定。
在目前这种情况下,
RTTI
造型只实现了一部分:
Object
造型成
Shape
,而不
是造型成
Circle
,
Square
或者
Triangle
。那是由于我们目前能够肯定的唯一事实
就是
Vector
里充斥着几何形状,而不知它们的具体类别。在编译期间,我们肯定
的依据是我们自己的规则;而在编译期间,却是通过造型来肯定这一点。
现在的局面会由多形性控制,而且会为
Shape
调用适当的方法,以便判断句
柄到底是提供
Circle
,
Square
,还是提供给
Triangle
。而且在一般情况下,必须保
证采用多形性方案。因为我们希望自己的代码尽可能少知道一些与对象的具体类
型有关的情况,只将注意力放在某一类对象(这里是
Shape
)的常规信息上。只
有这样,我们的代码才更易实现、理解以及修改。所以说多形性是面向对象程序
设计的一个常规目标。
然而,若碰到一个特殊的程序设计问题,只有在知道常规句柄的确切类型后,
才能最容易地解决这个问题,这个时候又该怎么办呢?举个例子来说,我们有时
候想让自己的用户将某一具体类型的几何形状(如三角形)全都变成紫色,以便
突出显示它们,并快速找出这一类型的所有形状。此时便要用到
RTTI
技术,用
它查询某个
Shape
句柄引用的准确类型是什么。
11.1.1 Class
对象
为理解
RTTI
在
Java
里如何工作,首先必须了解类型信息在运行期是如何表
示的。这时要用到一个名为“
Class
对象”的特殊形式的对象,其中包含了与类
有关的信息(有时也把它叫作“元类”)。事实上,我们要用
Class
对象创建属于
评论