java多态+多态中隐含的问题

来源:互联网 发布:lua ide vscode 编辑:程序博客网 时间:2024/06/04 18:52

【0】RAEDME

0.1)本文总结于 core java volume 1, 感觉多态中存在的这个问题很新颖,故分享之;


【1】继承与is-a法则

1.1)有一个用来判断是否应该设计为继承关系的规则: 这就是 is-a 规则, 它表明子类的每个对象也是超类的对象;
1.2)is-a法则: is-a 法则 的另一种表述法是 置换法则, 它表明程序中出现超类对象的任何地方都可以用子类对象置换;
如, 可以将子类的对象赋给超类变量:

Employee e;e = new Employee();e = new Manager();

【2】多态

2.1)多态定义: 在java中, 对象变量是多态 的, 一个 Employee变量既可以引用一个 Employee 类对象,也可以引用一个 Employee 类的 任何子类对象;
2.2)从以下代码,就可以看出 置换法则的优点:

Manager boss = new Manager(......);Employee[] staff = new Employee[3];staff[0] = boss;staff[1] = new Employee("tangtang", 1, 2, 3, 4);staff[2] = new Employee("rongrong", 4, 3, 2, 1);

2.3)在上面的代码中, 变量 staff[0] 和 boss 引用同一个对象, 但编译器将 staff[0] 看做是 Employee对象;
2.4)这意味着, 可以这样调用 boss.setBonus(…) ;但是不可以这么调用: staff[0].setBonus(……); 这是因为 staff[0] 声明的类型是 Employee, 而setBonus 不是 Employee 类的方法;
2.5)也不能将一个超类的引用赋给子类变量,下面的赋值是非法的:
Manager m = staff[i]; 非法;原因很清楚, 不是所有的雇员都是经理;
Alert) 在java中, 子类数组的引用可以转换成超类数组的引用, 而不需要采用强制类型转换, 如,下面是一个经理数组:

Manager[] managers = new Manager[10];

将它转换为 Employee 数组是完全合法的:

Employee[] staff = managers; 

【3】java多态机制存在的问题(很隐秘, 这个问题)

3.1)这样做后,存在的问题(切记 managers 和 staff 引用的是同一个数组):
如, staff[0] = new Employee(“XiaoTang”, ……);
编译器竟然接纳了这个赋值操作。但这里, staff[0] 和 managers[0] 引用的是同一个对象, 似乎我们把一个普通员工归入经理的行列了, 这是一种很忌讳发生的事情;当调用 managers[0].setBonus(10000)的时候, 将会导致调用一个不存在的实例域, 进而搅乱相邻存储空间的内容;
3.2)为了确保不发生这类错误, 所有数组都要牢记创建它们的元素类型,并负责监督仅将类型兼容的引用存储到数组中;
这里写图片描述

0 0
原创粉丝点击