本帖最后由 Porsche911 于 2014-3-26 18:31 编辑
这篇心得的内容可对于大多数同学来说都十分简单,甚至觉得是常识,但我确实费了一番功夫才基本搞懂,所以还望给位大神轻拍!如有错误,还请指正!
--------------------------------------------------分割线--------------------------------------------------------------------------------------------------
关于多态,对于父类引用指向子类对象,我一直有一个疑问,到底这个引用型变量的类型是父类还是子类?你要说是父类吧,当调用非静态方法时,运行的是子类方法;你说是子类吧,调用成员变量时又是调用父类的变量,十分迷惑人。经过一番思考,再结合我昨天在论坛提的一个问题(原帖地址:http://bbs.itheima.com/thread-111337-1-1.html),结论如下:
父类引用指向子类对象,这个引用大体上就是就是父类。证据如下:
1.非静态方法。
就拿Father f = new Father(); f.f(); 这两句代码为例,当父类引用型变量f调用f()方法时,他首先尝试调用父类的方法,但如果检测到有子类继承了父类,并覆盖了父类中的方法时,就会去调用子类的方法(这仅仅是我自己的理解,Java真实的运行机制并不一定是这样。。。)。我们可以这样去理解上述内容的逻辑,既然子类继承了父类,并复写了父类中旧有的方法,那么子类中的新方法,必然是对父类旧方法的增强、提升和改进,否则就没有复写的必要,既然子类中的新方法更好,那么虚拟机可能默认会在这种情况下去调用子类新的更好的方法,而不运行父类的旧方法。在这里可能Java内部的机制将父类中的旧方法和子类中的新方法联系了起来,当调用父类的方法时自动指向了子类的方法。我们应该把子类想成是在父类基础上的增强和提升,而不是独立的一个新的类,子类的核心还是父类。
2.变量
当父类引用型变量调用成员变量时还是会首先去调用父类的变量。上述的思路也可以用在这里。因为当子类继承了父类,并想使用父类的成员变量时,没有必要重新定义一个同名变脸,直接拿来用就可以了,这与方法是不一样的,因为变量不存在什么更强更好这种说法。因此,父类引用型变量调用成员变量时只会调用父类自己的变量。
3.我另外一个帖子也可以说明这个问题(地址在上面)。
当父类的方法被私有化时,即使子类继承父类,并定义了与父类完全相同的方法,也不能复写父类的方法,因为父类私有方法对子类不可见。因此,当父类引用型变脸调用f()方法时,还是首先尝试调用父类的旧方法,而在这里子类既然没有复写父类的方法,那也就只能是调用父类的旧方法了(说的有点儿啰嗦。。。)。而这个例子巧妙之处就在于,他是在本类中创建本类对象,并用父类引用型变量指向这个对象,这个引用型变量其实是成员变量,成员变量和成员函数之间的调用是无视私有限制,所以能够运行成功。也正是通过这个看似错误的例子,才能稍微理解这里面的机理。
总结一句话就是:当父类引用型变量调用(子父类的)成员变量或者成员函数时,首先尝试调用父类的变量或方法,只有当子类复写了父类的方法时才会调用子类的方法。 |