文档详情

第十一章 运行期类型鉴定.pdf

发布:2015-09-08约2.7万字共16页下载文档
文本预览下载声明
第 11章 运行期类型鉴定 运行期类型鉴定(RTTI)的概念初看非常简单——手上只有基础类型的一个句柄时,利用它判断一个对象的 正确类型。 然而,对RTTI的需要暴露出了面向对象设计许多有趣(而且经常是令人困惑的)的问题,并把程序的构造问 题正式摆上了桌面。 本章将讨论如何利用Java在运行期间查找对象和类信息。这主要采取两种形式:一种是“传统”RTTI,它假 定我们已在编译和运行期拥有所有类型;另一种是Java1.1特有的“反射”机制,利用它可在运行期独立查 找类信息。首先讨论“传统”的RTTI,再讨论反射问题。 11.1对 RTTI的需要 请考虑下面这个熟悉的类结构例子,它利用了多形性。常规类型是Shape类,而特别衍生出来的类型是 Circle,Square和Triangle。 这是一个典型的类结构示意图,基础类位于顶部,衍生类向下延展。面向对象编程的基本目标是用大量代码 控制基础类型(这里是Shape)的句柄,所以假如决定添加一个新类(比如Rhomboid,从Shape衍生),从 而对程序进行扩展,那么不会影响到原来的代码。在这个例子中,Shape接口中的动态绑定方法是draw(), 所以客户程序员要做的是通过一个普通Shape句柄调用draw()。draw()在所有衍生类里都会被覆盖。而且由 于它是一个动态绑定方法,所以即使通过一个普通的Shape句柄调用它,也有表现出正确的行为。这正是多 形性的作用。 所以,我们一般创建一个特定的对象(Circle,Square,或者Triangle),把它上溯造型到一个Shape(忽 略对象的特殊类型),以后便在程序的剩余部分使用匿名Shape句柄。 作为对多形性和上溯造型的一个简要回顾,可以象下面这样为上述例子编码(若执行这个程序时出现困难, 请参考第3章3.1.2小节“赋值”): //: Shapes.java package c11; importjava.util.*; interface Shape { void draw(); } class Circle implements Shape { public void draw() { System.out.println(Circle.draw()); } } class Square implements Shape { 333 public void draw() { System.out.println(Square.draw()); } } class Triangle implements Shape { public void draw() { System.out.println(Triangle.draw()); } } public class Shapes { public static void main(String[] args) { Vector s = new Vector(); s.addElement(new Circle()); s.addElement(new Square()); s.addElement(new Triangle()); Enumeration e = s.elements(); while(e.hasMoreElements()) ((Shape)e.nextElement()).draw(); } } ///:~ 基础类可编码成一个interface(接口)、一个abstract(抽象)类或者一个普通类。由于Shape没有真正 的成员(亦即有定义的成员),而且并不在意我们创建了一个纯粹的Shape对象,所以最适合和最灵活的表 达方式便是用一个接口。而且由于不必设置所有那些abstract关键字,所以整个代码也显得更为清爽。 每个衍生类都覆盖了基础类draw方法,所以具有不同的行为。在main()中创建了特定类型的Shape,然后将 其添加到一个Vector。这里正是上溯造型发生的地方,因为Vector只容纳了对象。由于Java中的所有东西 (除基本数据类型外)都是对象,所以Vector也能容纳Shape对象。但在上溯造型至Object的过程中,任 何特殊
显示全部
相似文档