什么是多態(tài)
- 面向?qū)ο蟮娜筇匦裕悍庋b夷野、繼承、多態(tài)拇泛。從一定角度來看滨巴,封裝和繼承幾乎都是為多態(tài)而準備的。這是我們最后一個概念俺叭,也是最重要的知識點恭取。
- 多態(tài)的定義:指允許不同類的對象對同一消息做出響應(yīng)。即同一消息可以根據(jù)發(fā)送對象的不同而采用多種不同的行為方式熄守。(發(fā)送消息就是函數(shù)調(diào)用)蜈垮。
- 實現(xiàn)多態(tài)的技術(shù)稱為:動態(tài)綁定(dynamic binding),是指在執(zhí)行期間判斷所引用對象的實際類型柠横,根據(jù)其實際的類型調(diào)用其相應(yīng)的方法窃款。
- 多態(tài)的作用:消除類型之間的耦合關(guān)系。
- 現(xiàn)實中牍氛,關(guān)于多態(tài)的例子不勝枚舉晨继。比方說按下 F1 鍵這個動作,如果當前在 Flash 界面下彈出的就是 AS 3 的幫助文檔搬俊;如果當前在 Word 下彈出的就是 Word 幫助紊扬;在 Windows 下彈出的就是 Windows 幫助和支持。同一個事件發(fā)生在不同的對象上會產(chǎn)生不同的結(jié)果唉擂。
- 多態(tài)存在的三個必要條件 1餐屎、要有繼承; 2玩祟、要有重寫腹缩; 3、父類引用指向子類對象。
上菜
public class A {
public String show(D obj) { //方法一
return ("A and D");
}
public String show(A obj) { //方法二
return ("A and A");
}
static class B extends A {
public String show(B obj) { //方法三
return ("B and B");
}
public String show(A obj) { //方法四
return ("B and A");
}
}
static class C extends B {
}
static class D extends B {
}
public static void main(String[] args) {
A a2 = new B();
A a1 = new A();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
// 創(chuàng)建了B對象 類型是A 藏鹊,調(diào)用超類函數(shù)润讥,子類重寫了 調(diào)用子類的
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
// 子類沒有 去找超類
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
System.out.println("10--" + d.show(d));
}
}
實驗結(jié)果
1--A and A
2--A and A
3--A and D
4--B and A
5--B and A
6--A and D
7--B and B
8--B and B
9--A and D
10--A and D
讓我們分析一下,理清其中各個類的繼承關(guān)系
- 那我們開始分析輸出A a1 = new A();這是普通的創(chuàng)建對象盘寡,故a1擁有調(diào)用方法一和方法二的能力楚殿。那么究竟調(diào)用哪個方法呢,這里面涉及方法的重載竿痰。其實脆粥,在編譯的時候,編譯器已經(jīng)進行了前期綁定影涉,即把show()变隔;方法與類中的方法主體2進行綁定。就是說常潮,在編譯時弟胀,系統(tǒng)就已經(jīng)知道應(yīng)該調(diào)用哪個方法,即使你有方法的重載喊式。
- 故 a1.show(b)會與方法二綁定孵户;a1.show(c)會與方法二綁定;a1.show(d)會與方法一綁定岔留。且都在編譯時完成綁定夏哭。
- 但A a2 = new B();就涉及了多態(tài) 了,B實現(xiàn)了向上轉(zhuǎn)型献联。創(chuàng)建了一個父類引用竖配,指向子類對象。這樣的做法很常見里逆,因為這樣不僅增加了靈活性(父類引用可以隨時指向任意子類對象)进胯,也提高了擴展性。但要知道的是原押,向上轉(zhuǎn)型的缺點胁镐,就是不能調(diào)用子類中有而父類沒有的方法。
- 故A a2 = new B();中诸衔,方法四對方法二進行了重寫盯漂,所以a2擁有調(diào)用方法一和方法四的能力,而方法三不能調(diào)用(由上一段可知)笨农。所以就缆,在編譯時, a2.show(b)會與方法四綁定谒亦; a2.show(c)會與方法四綁定竭宰; a2.show(d)會與方法一綁定空郊。
- B b = new B();這是普通的創(chuàng)建子類對象,B繼承于A羞延,且方法四重寫了方法二渣淳,所以b擁有調(diào)用方法一脾还,方法三伴箩,方法四的能力。所以b.show(b)會與方法三綁定鄙漏,b.show(c)會與方法三綁定嗤谚,b.show(d)會與方法一綁定。