黑马程序员技术交流社区
标题: 继承中同名变量的问题。 [打印本页]
作者: 移动小坦克 时间: 2013-3-9 01:42
标题: 继承中同名变量的问题。
这段代码是Zi继承Fu,在两个类中都有一个叫num的变量,和叫show的函数
问题1,当zi继承Fu,那么子类中也会有Fu类的变量 int num=5,但是子类也有同名的变量,也就说子类有两个int型的叫num的变量,
但是没有报错原因是什么?父类变量到底有没有被继承?如果继承了,同名的情况下没有报错,那如何区分?
问题2,执行这段f.show();是执行了Zi类中的代码,因为复写,但是System.out.println(f.num);发现打印5,原因是什么?
class Fu
{
int num = 5;
public void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
int num =8;
public void show()
{
System.out.println("zi show");
}
}
public class TestExtends {
public static void main(String[] args)
{
Fu f = new Zi();
System.out.println(f.num);
f.show();
}
}
作者: 夏振博 时间: 2013-3-9 02:08
如果子类和父类有相同的方法,即子类重写了父类的方法,那么执行的方法是子类的。即调用谁的方法,由实体对象类型来决定。能调用什么方法,由引用类型来决定。
在多态中成员函数的特点 :在编译时期:参阅引用型变量多数的类中是否有调用的方法,如果有,编译通过,如果没有便以失败。在运行时期:参阅的是对象所属的类中是否有调用的方法。简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。在多态中成员变量的特点:无论编译和运行都参考左边(引用型变量所属的类)。在多态中静态函数的特点:无论编译和运行,都参考左边。只要引用在,就找引用型变量所属类中的内容。静态方法一进内存就已经绑定在该方法所属的类上了。
以前看别人日志时收入的,希望对你有帮助
作者: 移动小坦克 时间: 2013-3-9 02:10
夏振博 发表于 2013-3-9 02:08 
如果子类和父类有相同的方法,即子类重写了父类的方法,那么执行的方法是子类的。即调用谁的方法,由实体对 ...
这个我也知道,不是我要的答案啊。。。。。。
作者: 张亚青 时间: 2013-3-9 02:37
问题一:
在继承中,父类的非私有变量确实会被继承,但如果子类中又出现同名成员变量时,并不会报错,
子类要访问本类中的变量,用this
子类要访问父类中的同名变量,用super
问题二:
1、在多态中【<非静态>成员函数】的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,否则失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
就比如:我要一个动物(父类),然后给出一个猫(子类对象),他们都包含“叫”这个方法,然后我让这个动物叫一下,结果动物就会“喵喵”叫,即运行的是子类的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
所以 f.show()运行的是f 创建对象所属类即Zi类中的show()方法;
2、在多态中,【成员变量】的特点:
无论编译和运行,都参考左边(引用变量所属的类)。
也就是说f.num的值是声明f类型时的类中的值。
就比如:我要一个动物(父类),其中包含变量“特征”(会运动),然后给出一个猫(子类对象),里面也包含变量“特征”(会抓老鼠),然后我指着猫问动物的特征是什么,结果肯定是动物的“特征”是会运动,总不能说动物的“特征”是会抓老鼠吧!也就是输出变量“特征”的值是声明类型的类的值。
3、在多态中,【静态成员函数】的特点:
无论编译和运行,都参考左边。
作者: amen0205 时间: 2013-3-9 02:42
其实这个问题要答案不好要 只能是从结果推导 既然已经是这样了 那好 我开始推导原因 然后好到了一个能理解的方式 那就OK了 如果一直不能理解 也没事 知道这么用 不用错就OK
按我的理解 子父类同名变量 可以理解为 我继承了父类 所以 所以我可以用 可以说我有 也可以说我没有 在多态中 父类引用指向了子类对象 用父类引用调用会返回父类的变量 这里有人就说了一种隐式父类的理解 就是说 我是一个子类 我建立对象 就会隐式的建立一个父类对象
在类与类之间的继承中,当我们用父类的引用指向子类对象时,这个引用也就指向子类对象中的父类对象
Java引用变量有两个类型,一个是编译时的类型,一个是运行时的类型。编译时的类型是由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。通过引用变量来访问其包含的实列属性时,系统总是试图访问它编译时类所定义的属性。而不是它运行时类型所定义的属性。
还是那句好 不能理解 记住就好
作者: 何旭程 时间: 2013-3-9 03:09
关于多态时成员变量的问题参考如下:
编译时:参考引用型变量所属的类中的是否有被调用的成员变量,如果有,则编译成功,否则,编译失败
运行时:参考引用型变量所属的类中的是否有被调用的成员变量,如果有,则调用该成员变量
作者: 何旭程 时间: 2013-3-9 03:29
hexucheng_hm 发表于 2013-3-9 03:09 
关于多态时成员变量的问题参考如下:
编译时:参考引用型变量所属的类中的是否有被调用的成员变量,如果有 ...
抱歉,刚才复制了看视频时记下的笔记粘帖了直接发了。。。。。{:2_33:}。编译的时候是看父类中有没有num这个成员变量,你的代码里有,所以编译通过了;至于运行时的值, Fu f = new Zi();由这句代码,创建的子类对象被提升成了父类型,所以引用成员变量num时是引用父类的num成员变量值;另外,关于有几个num变量的问题,我觉得只有一个,因为只创建了一个子类对象,其中不可能有两个同名变量,父类的num成员变量是被继承了的,在 Fu f = new Zi();这句代码的前提下,不会有如何区分的困扰,因为子类型已经被提升成了父类型。
作者: 邹学良 时间: 2013-3-9 09:21
这个在毕老师讲的多态中讲得很清楚了的
当在执行Fu f = new Zi()时,做为多态的特点:
当f.num引用F去查找NUM值时,因为是父类引用,它是先从父类中开始进行查找,如果本类中有NUM值,就直接打印本类的值,如果没有就才去查找子类NUM。也就是说,在多态中,成员变量无论是在编译还是运行是,数据查找都是以引用型变量所属的类为先。
如换成Zi f = new Zi()
NUM值打印的就成了子类NUM值
而当多态中的成员方法调用F。SHOW()时,它运行时只看在堆中的实例对象所属那个类,因为真正调用的还是实例对象,也就是它打印的是子类的原因所在
作者: 邹学良 时间: 2013-3-9 09:21
这个在毕老师讲的多态中讲得很清楚了的
当在执行Fu f = new Zi()时,做为多态的特点:
当f.num引用F去查找NUM值时,因为是父类引用,它是先从父类中开始进行查找,如果本类中有NUM值,就直接打印本类的值,如果没有就才去查找子类NUM。也就是说,在多态中,成员变量无论是在编译还是运行是,数据查找都是以引用型变量所属的类为先。
如换成Zi f = new Zi()
NUM值打印的就成了子类NUM值
而当多态中的成员方法调用F。SHOW()时,它运行时只看在堆中的实例对象所属那个类,因为真正调用的还是实例对象,也就是它打印的是子类的原因所在
作者: 王军行 时间: 2013-3-9 13:16
我的理解是:
问题1:父类,子类毕竟是两个类他们各自的成员在各自的空间。看似同名其实在不同的位置,在计算机看来不是同一个变量而是两个空间的变量可以用空间(所属类)来区分,所以jvm是可以区分的不会编译出错,所以变量继承是继承了(子类中没有同名变量可以直接用子类对象调用这个变量可以说明确实继承了)但是不存在覆盖问题,我们也可以用调用它的对象所属的类类型来区分,父类型引用(不管指向父类对象还是子类对象)调用的就是父类空间的变量,子类型引用调用的就是子类的变量
问题2.问题1已经说了,f是父类型的引用调用的变量就是父类中的但是注意调用的方法子类中存在同名会覆盖
f如果调用子类中的变量就得转换类型,想调用父类中的方法只能在子类中用super或者干脆建立父类对象
希望对你有点帮助,不好理解,其实最简单还是记住毕老师的结论
作者: 移动小坦克 时间: 2013-3-9 20:03
本帖最后由 韩松范 于 2013-3-9 20:07 编辑
王军行 发表于 2013-3-9 13:16 
我的理解是:
问题1:父类,子类毕竟是两个类他们各自的成员在各自的空间。看似同名其实在不同的位置,在计 ...
看了这么多答案,感觉也就这个和门文通的靠铺,至少是试图按着我思考的思路答题,真正在乎我问的是什么
其他的都是在告诉我访问规则。
我知道规则,我不是问1+1等于几,
而是问为什么1+1 = 2,大家的回答基本都是因为1+1=2,所以1+1=2的套路。。。。。。。
版主这个回答没给技术分,我帮着申请一下
还有顺便问一下,为什么回答的都有技术分,问问题的我就没有。。。。。。。。。。。
| 欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |