JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

java 核心技术-12版 卷Ⅰ- 5.1.5 多态

wys521 2024-11-28 09:00:05 精选教程 20 ℃ 0 评论

原文

5.1.5 多态

有一个简单的规则可以用来判断是否应该将数据设计为继承关系,这就是“is-a”规则,它指出子类的每个对象也是超类的对象。例如,每个经理都是员工,因此,将 Manager 类设计为 Employee 类的子类是有道理的;反之则不然,并不是每一名员工都是经理。

“is-a”规则的另一种表述是替换原则(substitution principle)。它指出程序中需要超类对象的任何地方都可以使用子类对象替换。

例如,可以将子类的对象赋给超类变量。

Employee e;

e = new Employee(...); // Employee object expected

e = new Manager(...); // 0K, Manager can be used as well

在Java程序设计语言中,对象变量是多态的(polymorphic)。一个Employee 类型的变量既可以引用一个Employee 类型的对象,也可以引用 Eployee 类的任何一个子类的对象(例如Manager、Executive、Secretary等)。

在程序清单5-1 中,我们就利用了这个替换原则:

Manager boss = new Manager( ... );

Employee[] staff = new Employee[3];

staffp[0] = boss;

在这个例子中,变量staff[0] 与boss 引用同一个对象。但编译器只将staff[0] 看成是一个Employee 对象。

这意味着,可以这样调用

boss.setBonus(5000);// OK

但不能这样调用

staff[0] .setBonus(5000); // ERROR

这是因为staff[0]声明的类型是Employee ,而setBonus 不是Employee 类的方法。

不过,不能将超类的引用类型赋给子类变量。例如,下面的赋值是非法的:

Manager m = staff[i];// ERROR

原因很清楚:不是所有的员工都是经历。如果赋值成功,那么m 有可能引用了一个不是经理的Employee 对象,而在后面有可能会调用 m.setBonus( ... ),这就会发生运行时错误。

警告:在Java 中,子类引用数组可以转换成超类引用数组,而不需要使用强制类型转换。例如,下面是一个经理数组

Manager[] managers = new Manager[10];

将它转换成 Employee[] 数组完全是合法的:

Employee[] staff = managers; // 0K

这样做肯定不会有问题,请思考一下其中的缘由。毕竟,如果 manager[i] 是一个Manager,它也一定是一个 Employee。不过,实际上会发生一些令人惊讶的事情。要切记 managers和staff 引用的是同一个数组。现在看一下这条语句:

staff[0] = new Employee("Harry Hacker” , ... );编译器竟然接纳了这个赋值操作。但在这里,staff[0] 与 manager[0] 是相同的引用似乎我们把一个普通员工擅自归入经理行列中了。这非常糟糕,当调用 managers[0].setBonus(1000)的时候,将会试图访问一个不存在的实例字段,进而搅乱相邻存储空间的内容。

为了确保不发生这类破坏,所有数组都要牢记创建时的元素类型,并负责监督仅将类型兼容的引用存储到数组中。例如,使用 new Manager[10]创建的数组是一个经理数组。如果试图存储一个Employee 类型的引用就会引发ArrayStoreException 异常。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表