分享
 
 
 

我看多态——多态的学习笔记

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

发现好多初学的朋友对多态部分总是比较模糊,小弟今天在看朋友的学习笔记的时候也发现这个问题,所以借我朋友笔记上的问题,发表一下自己的看法,先假设有继承关系如下的类: 代码:

Animal

|

Mammal

|

---------------------------------------------------------------

| | | |

Dog Cat Raccoon SwampThing

(implements (implements

Washer) Washer)

? interface Washer {}

? class Animal {}

? class Mammal extends Animal {}

? class Dog extends Mammal {}

? class Cat extends Mammal implements Washer {}

? class Raccoon extends Mammal implements Washer {}

? class SwampThing extends Mammal {}

下面的为对这几个类的应用和我朋友的笔记:

public class Test14 {

public static void main(String[] a) {

//----------------------------------

Dog rover,fido;

Animal anim;

rover =new Dog();

anim=rover; //理解成Animal anim = new Dog();

fido =(Dog)anim; //这段话能够通过编译和运行!!!!!

//fido =anim;不能通过编译

//----------------------------------

Washer wawa=new Cat();

SwampThing pogo;

pogo=(SwampThing)wawa;

//这句话能够通过编译,但不能运行

//两个毫不相干的类对象,居然能够通过编译?

//经另外测试,任意两个不相干的类对象cast是会出现编译错误的,

//所以,上面的类可能是继承了同一个类的缘故?

我的解释:

首先,我们知道,超类类型的变量可以引用一个子类类型的对象,即

代码:

Animal anim = new Dog();

这样是完全可以的,但是要注意的是编译器只检查且承认定义时候的类型,所以这样定义并赋值的anim变量不能调用Dog类中特有的实例字段和方法,这就是我们通常所说的隐藏,如果我们仍然要用到这些被隐藏的东西怎么办呢,那就是后面我们看到的笔者认为费解的那句:

代码:

fido =(Dog)anim;

其实这样只是恢复了被隐藏的功能,并不是把超类对象赋给子类变量,当然,编译器并不管最终这个造型转换能否成功,编译器现在只知道你在把一个Dog型的对象赋值给一个Dog型的变量,这当然没有问题,同样,后面的这样3句

代码:

Washer wawa=new Cat();

SwampThing pogo;

pogo=(SwampThing)wawa;

也很好理解,编译器只知道你在试图把一个SwampThing型的对象赋值给一个SwampThing型的变量,这当然没问题,注意对象wawa原来是什么类型编译器并不管(这句话并不全面,具体见下面),它只知道不管什么类型已经强制转换成了SwampThing型,至于这种转换会否成功则会在运行时判断,如果不能成功转换当然会抛出异常,这就是为什么总说造型前请用instanceof判断对象本身是否属于要转换的类!

让我们探讨的再深一点:

注意笔者上边最后注释的话是不对的,

Cat类与SwampThing类不是毫不相干的,它们都实现了Washer接口,注意变量wawa被定义的类型并不是Cat类型,而是Washer接口类型,所以

代码:

pogo=(SwampThing)wawa;

这句话才有可能成功,如果变量wawa被定义为Cat类型,则上面的造型绝对不可能成功,即编译也无法通过!由此我们知道,编译器也会为造型做出判断,不过编译器只会判断被造型的对象有没有可能被造型成功,就象上面的代码,wawa定义的时候是Washer类型,任何实现了这个接口的类的对象都可以被wawa引用,而SwampThing类也实现了这个接口,所以当编译器执行到上面的代码时,编译器只通过对wawa的定义检查,认为wawa有可能指向SwampThing类型的对象,这个造型有可能成功,所以可以被编译成功!

还可以再深一点讨论:

上面例子中笔者注释了这么一句话:

//fido =anim;不能通过编译

通过阅读之前的代码我们知道变量anim指向的实际对象和fido的定义类型是一致的,都是Dog,但是不能编译,这是因为编译器只检查anim的定义,发现是Dog的超类,所以我们必须要先类型转换,但是假设可以通过某种方法强制通过编译,那么这句话运行时反而没有问题因为实际类型是匹配的,这种情况可以说正好与上面讨论的能通过编译但是运行出错的情况相反!

总结:正是java中编译器只检查定义类型,运行时检查实际类型的双重检查方式造成了面向对象中多态这种即规范同时又非常有灵活性的机制

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有