封装、继承和多态是OOP的三大特性。其中多态的实现建立在前两者的基础之上,既是重点也是难点。我在初学Java时对这方面就难以理解,这次复习又认真揣摩了一下,在此记录自己的总结心得。
一、对象变量就是标签
在我看来,多态首先是给对象贴上标签。怎么理解呢?我们不妨先举个例子:
class Fruit{
public Fruit(){
System.out.println("这是一个水果");
}
}
class Apple extends Fruit{
public Apple() {
super();
}
public void printName() {
System.out.println("这是水果中的苹果");
}
}
class Banana extends Fruit{
public Banana() {
super();
}
public void printName() {
System.out.println("这是水果中的香蕉");
}
}
以上,我定义了一个水果类,以及继承它的苹果类和香蕉类。在Java中,首先对象变量是多态的,即父类对象变量既可以引用父类对象,也可以引用子类对象,即:
Fruit[] f = new Fruit[3];
f[0] = new Fruit();
f[1] = new Apple();
f[2] = new Banana();
可以看出,数组f的每个元素都是Fruit类的对象变量,但它们既可以引用Fruit类对象,也可以引用Apple类和Banana类的对象。这里我把对象变量理解成“标签”,标签就是对类的概括描述。我现在手上拿着水果标签,遇到一个水果类,直接就可以贴上去。遇到苹果呢?苹果当然是水果啊,贴!香蕉也是如此。可见,对象变量就是标签,标签就是对类的一个描述,只不过有准确描述和概括描述之不同罢了。
二、贴什么标签,就做什么事
在上述示例中,我们初步了解了对象变量就是标签。现在我们再来看一个例子:
Apple a = new Apple();
Fruit f = a;
a.printName();
f.printName(); //ERROR
其中a引用了一个Apple对象,可以调用printName()方法。然而,f虽然引用的也是Apple对象,但其本身只是Fruit标签,由于贴标签时描述的精确度不够,所以就不能确定其是否贴在了苹果上,也许只是普通的水果呢?你说你是个苹果,但你能拿出什么证据呢?贴在你身上的只是一个水果标签啊!所以为了安全起见,我们不能允许它调用这个方法。从中我们可以看出:贴什么标签,就做什么事,越俎代庖就是不行。
三、标签是脸蛋,做事落到实处
为了解决上述代码的问题,我在Fruit类中加入了printName()方法,以使其能够成功编译。然而,运行时我们可以看到,f.printName()调用的是Apple类的方法!这是为什么呢?之前不是说贴什么标签就做什么事吗?
其实我们这里陷入了一个误区。贴什么标签做什么事这个原则当然没错,但标签只是脸蛋,是没有能力做事的啊!所以,只要子类中存在同名方法,就一定要优先调用子类的方法。标签只是脸蛋,而做事却要落到实处,我的标签贴在谁身上,谁就来执行这个方法,就这么简单。
四、不同多态情况的理解辨析
在上面,我们讲了三个要点:1.对象变量是标签;2.标签规定了调用方法的权限;3.是对象而不是标签来调用方法。为了深入理解上述内容,我们来看几个例子:
- 多态情况下,子父类存在同名的成员变量时,访问的是父类的成员变量;
- 多态情况下,子父类存在同名的非静态成员函数时,访问的是子类的成员函数;
- 多态情况下,子父类存在同名的静态成员函数时,访问的是父类的成员函数;
- 多态情况下,不能访问子类特有的成员。
(此处引用部分出自【多态】@author 一大三千@大千世界)
如果深入理解了标签的意义,这几点就不难理解了。
第一点,标签其实就是脸蛋,成员变量作为对象的属性,当然也是对象的脸蛋。所以子父类存在同名成员变量时,必然访问父类成员变量。
第二点在前面已经说过,我们主要看一下第三点。为什么此处访问的是父类成员函数呢?不是说标签是脸蛋、做事落到实处吗?可偏偏静态方法是个特例,要知道静态方法其实是类的方法,是不依赖对象而存在的呀!所以静态方法不会被重写,只能被重载、隐藏和继承。此处一旦贴上父类的标签,子类的静态方法自然被隐藏起来,于是无法被调用,这当然是顺理成章的了。
第四点,其实也不用多说了。你的标签就是你的脸蛋、你的属性,父类标签上没贴的东西,子类又怎么能越俎代庖呢?其特有的成员变量和方法都是不能被访问的。
五、结语
本文总结了运行时多态的一些常见情况,并独创“标签”概念对各种情况进行辨析。当然,由于本人才疏学浅,又是第一次写博客,难免有不当之处。如有错误,还望有识之士不吝赐教。
本文通过标签概念深入解析Java中的多态特性,探讨对象变量、方法调用权限及对象执行方法的本质,辅以实例说明多态下成员变量与方法的访问规则。
1001

被折叠的 条评论
为什么被折叠?



