深入理解Java中的多態機制
引言:
多態通過分離做什麼和怎麼做,從另一個角度將接口和實現分離開來。多態不但能夠改善代碼的組織結構和可讀性,還能夠創建可擴展的程序--即無論在項目最初創建時還是在需要時添加新功能時都可以“生長”的程序。
本文目錄大綱:
一、什麼是多態
二、多態的類別
三、多態的產生方式
四、運行期多態必要條件
五、向上轉型
六、向下轉型
七、動態多態的適用範圍
八、多態的好處
1、什麼是多態
多態(Polymorphism),按字面的意思就是“多種狀態”。簡單而通俗的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
2、多態的類別
編譯期多態(靜態多態,早期綁定)和運行期多態(後期綁定);
綁定:將一個方法調用同一個方法主體關聯起來被稱做綁定。
前期綁定:在程序執行前綁定(由編譯器和連接程序實現),稱作前期綁定。它是面向過程的語言中不需要選擇就默認的綁定方式。列入C只有一種方法調用,那就是前期綁定。
後期綁定:在運行時根據對象的類型進行綁定。後期綁定也稱作動態綁定或運行時綁定。它通過某種特殊機制實現,即程序一直不知道對象的類型,但是方法調用機制調用機制能找到正確的方法體,並加以調用。
Java中除了static 方法和final 方法(private 屬於final 方法)之外,其他所有方法都是後期綁定。這意味着通常情況下,我們不必判定是否應該進行後期綁定--它會自動發生。
3、多態產生的方式
3.1、強制的:一種隱式做類型轉換的方法。
強制多態隱式的將參數按某種方法,轉換成編譯器認爲正確的類型以避免錯誤。在一下的表達式中,編譯器必須決定二元運算符‘+’所應做的工作:
[java] view plain copy
1. int a = 1 + 2;
2. double d = 2.0 + 2.0;
3. String s = "abc" + "def";
跟據需要判定"+ " 運算符所要進行的運算,(1和(2行中進行加法運算,(3中進行字符串連接運算
3.2、編譯期多態(重載 overload):
靜態多態性:包括變量的隱藏、方法的重載(指同一個類中,方法名相同(方便記憶),但是方法的參數類型、個數、次序不同,本質上是多個不同的方法);
舉例:
public class override{
public void show( ){
};
public void show( int i){
System.out.println("含參數的show方法 .");
};
}
通過傳入不同參數,讓程序根據傳入的參數來表現出不同的狀態。進而實現多態。
3.3、運行期多態(重寫 override)
動態多態性:是指子類在繼承父類(或實現接口)時重寫了父類(或接口)的方法,程序中用父類(或接口)引用去指向子類的具體實例,從代碼形式上看是父類(或接口)引用去調用父類(接口)的方法,但是在實際運行時,JVM能夠根據父類(或接口)引用所指的具體子類,去調用對應子類的方法,從而表現爲不同子類對象有多種不同的形態。不過,程序代碼在編譯時還不能確定調用的哪一個類的方法,只有在運行時才能確定,故又稱爲運行時的多態性。
舉例:
public classsup {
public void show(){
System.out.println("show() in sup !");
}
}
public classsub extendssup{
public void show(){
System.out.println("show() in sub !");
}
}
public classClient {
public static void main(String[] args) {
supsp= new sup();
subsb = new sub();
sups = new sub();
sp.show();
sb.show();
s.show();
}
}
運行結果:
show() in sup !
show() in sub !
show() in sub !
第三行代碼,雖然編譯是sup類,但運行的卻是sub的show()方法。通過方法的重載,讓程序表現出不同的狀態,來體現程序的多態性。
4、運行期多態必要條件
一、要有繼承(包括接口的實現);
二、要有重寫;
三、父類引用指向子類對象。
5、向上轉型
子類自有的方法不可見
1)、代碼檢查不允許。
2)、從實際意義上
在下面代碼中,s只能調用sup中曾聲明過的方法,而子類中新增加的所獨有的方法則並不可見,自然也無法調用。
sup s = new sub();
s.show();
6、向下轉型
存在於繼承中,父類引用指向的對象實際是要轉型的子類引用的類型。
假設現在已經定義一個了Animal類,並且定義類Dog和類Cat繼承Animal.
[java] view plain copy
1. 1) Animal a = new Dog();
2.
3. Dog d = (Dog) a; //正確
4.
5. 2) Animal a = new Cat();
6.
7. Dog d = (Dog) a; //拋異常
對於一個由向上轉型而來的對象,如果對它實行向下轉型,需要知道該對象之前的類型。否則編譯器會報錯。如上述代碼所描述一樣。
7、動態多態的適用範圍
1、只適用於動態方法,對於變量不能被重寫(覆蓋),”重寫“的概念只針對方法,如 變量不能被重寫(覆蓋)
2、靜態static方法屬於特殊情況,域不會有多態機制。所調用的方法根據編譯時採用的類型所確定。
下面通過代碼解釋:
/*
樣例1:
classParent{
int num = 3;
}
classChild extends Parent{
int num = 4;
}
*/
/*
樣例2:
class Parent{
}
class Child extends Parent{
intnum = 4;
}
*/
/*
樣例3:
class Parent{
void show(){
System.out.println("ParentShow!");
}
}
classChild extends Parent{
void show(){
System.out.println("ChildShow!");
}
}
*/
/*
樣例4:
class Parent{
}
class Child extends Parent{
voidshow(){
System.out.println("ChildShow!");
}
}
*/
class Parent{
static void show(){
System.out.println("ParentShow!");
}
}
class Child extends Parent{
static void show(){
System.out.println("ChildShow!");
}
}
public class PC{
public static void main(String[] args){
Parentp = new Child();
//樣例1:
//System.out.println(p.num);//3, 輸出的是父類的num;
//樣例2:
//System.out.println(p.num);//錯誤: 找不到符號 num
//樣例3:
//p.show();//ChildShow! 輸出的是子類的方法!
//樣例4:
//p.show();// 錯誤: 找不到符號 p.show();
//樣例5:
p.show();//Parent Show! 運行父類的靜態方法。
}
}
/*
總結:
對象多態時:
1.成員變量:(不涉及覆蓋)
編譯時: 參考引用變量所屬的類中是否有調用的成員變量,有, 編譯通過,沒有,編譯失敗。
運行時: 參考引用變量所屬的類中是否有調用的成員變量, 並運行該類所屬中的成員變量。
簡單的說:編譯和運行都參考等號的左邊。
2.成員函數(非靜態):
編譯時:參考引用變量所屬的類中是否有調用的成員變量, 有, 編譯通過, 沒有,編譯失敗:
運行時:參考的是對象所屬的類中是否有調用的函數。
簡單的說:編譯看左邊, 運行看右邊。
3.靜態函數, 變量:
編譯和運行都是參考左邊參數類型!
其實靜態方法不存在多態, 靜態方法是屬於類的,我們說的是對象的多態!靜態方法直接用類名調用就好了,
沒必要創建對象!
靜態的方法只能被靜態的方法所覆蓋!
8、多態的好處
1.可替換性(substitutability)。多態對已存在代碼具有可替換性。例如,多態對圓Circle類工作,對其他任何圓形幾何體,如圓環,也同樣工作。
2.可擴充性(extensibility)。多態對代碼具有可擴充性。增加新的子類不影響已存在類的多態性、繼承性,以及其他特性的運行和操作。實際上新加子類更容易獲得多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。
3.接口性(interface-ability)。多態是超類通過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。如圖8.3 所示。圖中超類Shape規定了兩個實現多態的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere爲了實現多態,完善或者覆蓋這兩個接口方法。
4.靈活性(flexibility)。它在應用中體現了靈活多樣的操作,提高了使用效率。
5.簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤其在處理大量對象的運算和操作時,這個特點尤爲突出和重要。
參考資料:http://www.cnblogs.com/hujunzheng/p/3872619.html