网站首页 > 精选教程 正文
原文
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 异常。
猜你喜欢
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 5.2.3相等测试与继承
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 5.2.4 hashCode方法
- 2024-11-28 Java入门书单
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.3.7 隐式参数与显式参数
- 2024-11-28 全网最完整的免费java教程讲义系列(四)——java的流程控制
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.6 对象构造 4.6.1重载
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 3.10 数组
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.3 自定义类
- 2024-11-28 2019年Java核心技术我整理了200多页pdf,今天分享给你
- 2024-11-28 java 核心技术12版卷1 - 1.3 Java applet 与 Internet
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)