1. 程式人生 > >深入理解JAVA多型

深入理解JAVA多型

何為多型,多型有什麼用,多型有什麼表現

多型是同一個行為具有多個不同表現形式或形態的能力。

比如說,你喜歡喝酒,你去酒店買酒讓服務員給你拿一瓶酒,這個時候服務員問你“要紅酒、白酒、洋酒”,這也是多型,下面給出一定程式碼演示
酒 a=new 洋酒();
酒 a=new 紅酒();
酒 a=new 白酒();
從上例就可以看出,酒有不同的形態,有不一樣的特性,這就是多型

多型的宣告

同樣用上面的例子給出解釋,例如我有一個類
class 酒{
String color;
}
以及還有幾個子類(洋酒、紅酒、白酒)派生自酒類,每個都有一個各自的特性變數price
這個時候以下宣告是合法的
酒 a=new 白酒();
然後 a.color=“白色”;這樣是沒問題的,因為你本身就是繼承與酒類,可以實現酒的方法以及變數,同時JAVA也是執行父類物件指向子類物件,但是如果你像下面這樣就是會報錯的
a.price=1000;
很多人就不明白了,明明是new的白酒類,是一個子類物件,為什麼還不能用自己的特性方法,這個時候你需要了解一下java的記憶體載入,首先是編譯看左邊,如果你父類中不存在這個變數,那麼根本通不過編譯,就別說後期的運行了。那麼,如果你問我需要執行這個變數,應該怎麼辦,這個時候就需要轉型了

向上轉型以及向下轉型

上轉型:是子類物件由父類引用,格式:parent p=new son
下轉型:是父類向下強制轉換到子類物件(前提是該父類物件必須是經過上轉型的物件)
一定注意這裡的前提,下轉型必須要經過上轉型才行,接著用上面的例子舉例
現在我們已經經過了上轉型:酒 a=new 白酒();
接下來就是下轉型:白酒 白=(白酒)a;
然後你現在白.price=1000;就可以運行了

上面的理論就這些了,下面給出兩道實際例子

提示:方法以及靜態變數是編譯看“左邊”,執行看“左邊”,變數是編譯看“左邊”,執行看“右邊”

public class demo2 {

public static void main(String[] args) {
	 	A a1 = new A();
		A a2 = new B();
		B b  = new B();
		C c  = new C(); 
		D d  = new D(); 
		System.out.println(a1.show(b));   
		System.out.println(a1.show(c));   
		System.out.println(a1.show(d));  
		System.out.println(a2.show(b));   
		System.out.println(a2.show(c));  
		System.out.println(a2.show(d));   
		System.out.println(b.show(b));    
		System.out.println(b.show(c));    
		System.out.println(b.show(d));      
	}
}
class A {
	public String show(D obj) {
		return ("A and D");
}

	public String show(A obj) {
		return ("A and A");
	}
}

class B extends A {
	//過載
	public String show(B obj) {
		return ("B and B");
	}
	//重寫
	public String show(A obj) {
		return ("B and A");
	}

}

	class C extends B {
}

	class D extends B {
}

輸出結果是:
A and A
A and A
A and D
B and A
B and A
A and D
B and B
B and B
A and D

關於上面程式碼的解釋如下:
1.首先我們需要明白,題目最開始我說的原則,以及,題目中有重寫方法和過載方法

(1)首先a1就是A的物件,所以直接呼叫A自身的方法,然後傳入的物件b,這個時候因為類A中沒有比配的方法,所以將物件b提升成父類a,然後找到比配的方法,輸出AA
(2)同(1),一個道理,只是提升多經歷了一步
(3)因為傳入的本身就是d物件,所以直接有比配的方法,直接列印
(4)這裡需要注意前面說的原則了,編譯看左邊,執行看右邊,所以首先去看父類中是否存在這個方法,找到了,這個show(A obj)方法,然而這個方法被B類重寫,所以執行B類的show(A obj)列印BA
(5)這裡存在一個問題,按道理執行看右邊,然後將C物件提升,列印應該是BB,然而結果卻是BA,這裡我們需要注意,編譯是看的左邊,如果類A都不存在這個方法,那麼編譯就直接報錯,所以,這個時候一樣是在類A裡面找,找到了show(A obj)方法,然後被重寫,所以列印BA
(6)同(5)一個道理,也是首先在類A裡面找到,然後有一個直接比配show(D obj)就可以直接列印AD
(7)(8)就很簡單了,本身就是類B的物件,所以直接在類B中尋找,然後找到了,就列印BB
(9)這裡需要注意,雖然是類B的物件,但是B是繼承的A類,所以A類的方法也可以使用,所以會比配到A類的show(D obj)列印AD

好了,這就是這個題的解釋,或許還有其他人的解釋和我不一樣,

以下我會給出我的總結

1.方法以及靜態變數是編譯看“左邊”,執行看“左邊”,變數是編譯看“左邊”,執行看“右邊”
2.有多型,先看父類方法是否存在,或者可以經過提升轉換,然後再看子類的重寫
3.繼承鏈中物件方法的呼叫存在一個優先順序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。