1. 程式人生 > >java中實現多型的機制是什麼,動態多型和靜態多型的區別?(java基礎一)

java中實現多型的機制是什麼,動態多型和靜態多型的區別?(java基礎一)

多型總結: 指向子類的父類引用由於向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是過載該方法。若子類重寫了父類中的某些方法,在呼叫該些方法的時候,必定是使用子類中定義的這些方法(動態連線、動態呼叫)。

一、多型的實現

  • Java實現多型有三個必要條件:繼承、重寫、向上轉型。
  1. 繼承:在多型中必須存在有繼承關係的子類和父類。
  2. 重寫:子類對父類中某些方法進行重新定義,在呼叫這些方法時就會呼叫子類的方法。
  3. 向上轉型:在多型中需要將子類的引用賦給父類物件,只有這樣該引用才能夠具備技能呼叫父類的方法和子類的方法。

只有滿足了上述三個條件,我們才能夠在同一個繼承結構中使用統一的邏輯實現程式碼處理不同的物件,從而達到執行不同的行為。

實現形式:

  • 在Java中有兩種形式可以實現多型。繼承和介面。

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{}
public class test25 {
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("1--"+a1.show(b));
System.out.println("2--"+a1.show(c));
System.out.println("3--"+a1.show(d));
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));
}
}

結果為:

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

當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。這句話對多型進行了一個概括。其實在繼承鏈中物件方法的呼叫存在一個優先順序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

首先我們分析5,a2.show(c),a2是A型別的引用變數,所以this就代表了A,a2.show(c),它在A類中找發現沒有找到,於是到A的超類中找(super),由於A沒有超類(Object除外),所以跳到第三級,也就是this.show((super)O),C的超類有B、A,所以(super)O為B、A,this同樣是A,這裡在A中找到了show(A obj),同時由於a2是B類的一個引用且B類重寫了show(A obj),因此最終會呼叫子類B類的show(A obj)方法,結果也就是B and A。

方法已經找到了但是我們這裡還是存在一點疑問,我們還是來看這句話:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。這我們用一個例子來說明這句話所代表的含義:a2.show(b);

這裡a2是引用變數,為A型別,它引用的是B物件,因此按照上面那句話的意思是說有B來決定呼叫誰的方法,所以a2.show(b)應該要呼叫B中的show(B obj),產生的結果應該是“B and B”,但是為什麼會與前面的執行結果產生差異呢?這裡我們忽略了後面那句話“但是這兒被呼叫的方法必須是在超類中定義過的”,那麼show(B obj)在A類中存在嗎?根本就不存在!所以這句話在這裡不適用?那麼難道是這句話錯誤了?非也!其實這句話還隱含這這句話:它仍然要按照繼承鏈中呼叫方法的優先順序來確認。所以它才會在A類中找到show(A obj),同時由於B重寫了該方法所以才會呼叫B類中的方法,否則就會呼叫A類中的方法。

所以多型機制遵循的原則概括為:當超類物件引用變數引用子類物件時,被引用物件的型別而不是引用變數的型別決定了呼叫誰的成員方法,但是這個被呼叫的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法,但是它仍然要根據繼承鏈中方法呼叫的優先順序來確認方法,該優先順序為:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

二、靜態多型和動態多型的區別:

多型分為編譯時多型和執行時多型。其中編輯時多型是靜態的,主要是指方法的過載,它是根據引數列表的不同來區分不同的函式,通過編輯之後會變成兩個不同的函式,在執行時談不上多型。而執行時多型是動態的,它是通過動態繫結來實現的,也就是我們所說的多型性。