“编译看左边,运行看右边”(多态执行)
含义:
Animal c = new Cat(); 左边是 Animal 类 (或接口) 右边是 Cat() 类; 在编译的时候编译器不管你右边是什么类,只要左边的 Animal 类 (或接口) 能编译通过就不会报错。但是运行的时候就要按照右边的 Cat()类实际情况来运行。
(对面向对象语言中理解多态、继承很有帮助~~~)
老毕在讲到多态执行问题时,结合下面的例子,给我们总结了一套口诀:“成员变量,静态方法看左边;非静态方法:编译看左边,运行看右边。” 意思是:当父类变量引用子类对象时(Fu f = new Zi();),在这个引用变量 f 指向的对象中,他的成员变量和静态方法与父类是一致的,他的非静态方法,在编译时是与父类一致的,运行时却与子类一致(发生了复写)。
例:
个人分析:
Fu f = new Zi();---------- 首先了解变量 F 到底是什么,把这句子分 2 段:Fu f; 这是声明一个变量 f 为 Fu 这个类,那么知道了 f 肯定是 Fu 类。然后我们 f=newZi(); 中建立一个子类对象赋值给了 f,结果是什么??
结果是,拥有了被 Zi 类函数覆盖后的 Fu 类对象 ----f------。
也就是说:
只有子类的函数覆盖了父类的函数这一个变化,但是 f 肯定是 Fu 这个类,也就是说 f 不可能变成其他比如 Zi 这个类等等 (突然 f 拥有了 Zi 类特有函数,成员变量等都是不可能的)。所以 f 所代表的是函数被复写后(多态的意义)的一个 Fu 类,而 Fu 类原来有的成员变量(不是成员函数不可能被复写)没有任何变化。
获得结论:
- 1、成员变量:编译和运行都看 Fu。
但是 f 的 Fu 类函数被复写了。
- 2、非静态方法:编译看 Fu,运行看 Zi
对于静态方法:编译和运行都看 Fu!!
其实很简单,首先我们要理解静态情况下发生了什么?当静态时,Fu 类的所有函数跟随 Fu 类加载而加载了。也就是 Fu 类的函数 (是先于对象建立之前就存在了,无法被后出现的 Zi 类对象所复写的,所以没发生复写,那么获得:
- 3、静态方法:编译和运行都看 Fu。