我在这里地下和我dennisboys的学习交流信件, 我们主要在谈java中多态性效果。
这里感谢我的好同学能给我一个结合自己能力解释效果的机会, 在解释中有出错
或许需求讨论的部分希望能告诉我一声。
上篇关于多态性的文章请参阅我前面写的.
*******************************************************************************
网友dennisboys的发问部分开始
*******************************************************************************
从头到尾把你的代码看了n次, 画了n个图(关于父类和子类的函数地址图), 有以下一些迷惑
test t=new test();
base b=new base();
b=t;
/*
效果一:
这里是把父类的援用指向子类, 那是不是说调用父类的方法就等于调用子类的方法呢?就是
如果b. display2()不是调用子类的display2()方法吗?而子类有display2()方法, 为什么不能
调用呢?(我试过写代码了, 果真如你所说是出错的。 )
对于以上的效果, 你有一段文字仿佛是对其作解译的。 不过我不太清楚。 不知是不是以下这
段。
援用原文:
同时可能有人要问, 子类中那个函数地址不是也在虚拟函数表中吗?
很快乐你问这样的效果, 但是父类援用看到的虚拟函数表是没有
那个函数项目的, 因为他对于父类援用相对是不可见。
我如今了解是如果在子类中如对方法作了更改或新增的方法, 对父类来说是不可见的?了解
对吗??
*/
效果二:
((test)b). display();
另一个迷感就是你说的强制转换类型的语法究竟是怎样的??我不明白为((test)b)代表什么
?? 不过说回来(我怎样觉得这个例子是在说继承??), 这个例子使我对继承有了很深的看法
??业故蔷醯枚远嗵?曰故且恢?虢猓?(别说我笨笨)可能我还没清楚究竟哪用到了多态性,
不过请先回复了我以上两个效果, 希望你回复了我以上两个效果(结合我研讨你的代码)使我
对多态性有更好更深的看法。 。
*******************************************************************************
网友dennisboys的发问部分完毕
*******************************************************************************
*******************************************************************************
zosatapo的解释部分开始
*******************************************************************************
你真的应该谢谢我的, 因为我辛辛苦苦打了篇文章,
因为网络缘由没有能成功保管, 害了我重写一次,
没有办法, 谁叫你是我的好同学呢。
首先谢谢你耐烦看完我的文章。
下面我就我上次写的那篇文章和你的效果作复杂的说明但是又比较复杂的说明。
我上次写的那篇文章存在一处写作错误, 我在网上已经修正了, 这里告诉你一下:
上次的原文中有这样的几句话
****************************************
// 下面调用会出错的
file://t. display2();
file://应该象下面那样
((test)b). display2();
******************************************
这几句话写作上有错误:
应该改成成下面这样:
**********************************************
// 下面调用[不]会出错的 (这里多了一个[不]字)
file://t. display2();
#########################################
实际上我下面这两行跟本文没有关系的
但是为了你很好的了解静态性, 你可以
把下面的代码与下面的停止比较。
#########################################
file://下面这行调用不会出错
file://b. display2(); 这里加了一行
file://应该象下面那样
((test)b). display2();
**********************************************‘
下面正式开始我们今天的话题, 正对你的效果我停止解释,
这里我尽可能的解释详细一点让你明白, 实际上这里太复杂
触及到OOP的具体完成效果,
姿美堂 这个效果又不得不触及到编译器
效果, 主要的又是对象内存布局效果。
由于第二个效果比较复杂, 我把回答效果的次序颠倒一下。
*********
效果二
*********
你说的很对, 我这里解的是继承, 但是我这里解的不只仅是继承的
效果。 可以这样是你说的继承只是我解释静态性效果的一个途径和
手腕而已, 因为继承和多态性一样是面向对象中很重要的概念, 不
是写一点文章就可以说明白的。
复杂一点和不精确的说, 静态性与是继承不可分割的, 如果没有继承
根本就谈不上多态性的。 所以我说你说的对, 但是你没有真正明白我
例子的作用(55555555~~~~~~~~~~~~~我的心血呀)
*********
效果一
*********
首先需求说明的是你对这个效果的了解是不正确的。
这个效果更是复杂的一塌懵懂, 我尽量用一些不标准的词汇来说明这个效果。
因为这样便于了解。 我这里不解太多的实际, 因为我自己如今也正在研讨jvm
标准的, 因为很多东西java和c++不同, 虽然两者完成很类似。 下面这点,
我是根据我团体的一些实践, 包括实际方面和顺序编写实践得到的。 但是
我也不敢全部拿c++的那套完成讲给你听, 实际上讲了你也不一定听得懂的。
我这里主要讲一些根本的知识, 你记住就可以了的, 等你学习深入的时分
我再给解释, 也许那时分你自然就懂了。
实际上在继承当前, 子类会重新设置自己的虚拟函数表,
这个虚拟函数表中的项目有由两部分组成。 从父类继承的虚拟函数和子类自己
的虚拟函数。
记住一个很复杂又很复杂的规则, 一个类型援用只能援用援用类型自身含有的
方法和变量。 你可能说这个规则不对的, 因为父类援用指向子类对象的时分,
援用是子类的方法的。 我告诉你这个规则对于这样的状况依然是成立的。 抓紧
你的大脑, 不要想一些乌七八糟的事情, 仔细听我分析。
对了, 到这里的时分我假定你对于下面的规则除了虚拟函数调用的状况下,
其他的静态函数援用, 以及变量援用都明白了。
下面我们开始我们的分量级说明。 虚拟函数援用。
下面是jvm标准中关于对象内存布局的说明, 我没有翻译
我想你可以看明白, 反正我如今看英文没有效果,
如果不明白就查字典。
The JavaVirtual Machine does not require any particular internal
structure for objects. In Sun's current implementation of the Java
Virtual Machine, a reference to a class instance is a pointer
to a handle that is itself a pair of pointers: one to a table
containing the methods of the object and a pointer to the
Class object that represents the type of the object, and
the other to the memory allocated from the Java heap for
the object data.
根据这里我就知道实际上jvm关于多态性支持解决方法是和c++中几乎一样的,
只是c++中编译器很多是把类型信息和虚拟函数信息都放在一个虚拟函数表中,
但是应用某种技术来区别。
所以当你运用父类援用指向子类的时分, 其实jvm已经运用了编译器发生的类型
信息调整转换了。 这里你可以这样了解, 相当于把不是父类中含有的函数从虚拟
函数表中设置为不可见的。 注意有可能虚拟函数表中有些函数地址由于在子类中
已经被改写了, 所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成
的方法体的地址了。
下面这一段就是为什么父类援用指向子类对象时分, 有的方法可以调用, 有的方法
却不能调用。
虚拟函数调用是经过虚拟函数表间接调用的, 所以才得以完成多态的。