標籤:例子 響應 訊息 print static 類類型 具體類 動態調用 好的
Java三大特性之多態
多態的定義:指允許不同類的對象對同一個訊息做出響應,即同一訊息可以根據發送對象的不同採用多種行為方式。
就我個人經曆來說,對一個新人一開始就理解這個定義還是有一點難度的(可能是我比較蠢)。我覺的還是用java的方式來理解可能會簡單一點:
多態就是指程式中定義的引用變數所指向的具體類型和通過該引用變數發出的方法調用在編程時並不確定,而是在程式運行期間才確定,即一個引用變數倒底會指向哪個類的執行個體對象,該引用變數發出的方法調用到底是哪個類中實現的方法,必須在由程式運行期間才能決定。因為在程式運行時才確定具體的類,這樣,不用修改來源程式代碼,就可以讓引用變數綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程式碼就可以改變程式運行時所綁定的具體代碼,讓程式可以選擇多個運行狀態,這就是多態性。
舉個大家都熟悉的例子,《木蘭詩》中有一句“雙兔傍地走,安能辨我是雌雄”;雌兔(A)和雄兔(B)都是兔子(rabbit)的子類,但是雙兔傍地走的時候你是分不出的,只有抓起來看看眼睛才能區別(雄兔腳撲朔,雌兔眼迷離)。下面我們可以用java代碼來表示“雙兔 ”:
Rabbit a = 雌兔;
Rabbit b= 雄兔;
在這裡表現的就是多態,雌兔和雄兔都是兔子的子類,我們通過父類可以引用不同的子類-------我們只有在啟動並執行時候才會直到參考型別所指向的具體執行個體對象
A a= new A();
這很容易理解,無非就是執行個體化了一個雌兔對象,但是你看下面這樣呢???
Rabbit r= new A();
我們可以這樣理解,這裡定義了一個Rabbit r,它指向了 A 對象執行個體。由於A與Rabbit是繼承關係,所以A可以向上轉型成Rabbit,所以r是可以指向A的執行個體對象的。。。這樣做有一個非常非常好的好處:在上一次繼承中我們講了,子類是父類的擴充,它可以提供比父類更為強大的功能,如果我們定義了一個指向子類的父類參考型別,那麼他除了能引用父類的共性外,還可以使用子類強大的功能。
但是向上轉型存在一些缺陷,就是它必然會導致一些方法屬性的丟失,使我們不能夠擷取他們:所以就有:父類類型引用可以調用父類中定義的方法和屬性,但是對於子類中的方法和屬性就望塵莫及了
我們來看一下代碼:
public class Rabbit{
public void fun1(){
System.out.println(" ------------------->Rabbit的fun1()")
public void fun2(){
System.out.println("----------Rabbit的fun2()")
}
}
}
public class A(){
/*
* 子類重載父類的方法,父類中不存在該方法,父類是不能引用該方法
*/
public void fun1(String a){
System.out.println("------------->A的fun1()")
}
/*
* 子類重寫父類方法,指向子類的父類引用調用fun2()的時候必然會調用子類中的*fun2()
*/
public void fun2(){
System.out.println("----------->A的fun2()")
}
}
我們測試一下:
public class Test{
public static void main(String args[]){
Rabbit r = new A();
r.fun1();
r.fun2();
}
}
______________________________________________________________________
Output:
------------------------->Rabbit的fun1()
-------------------------->A的fun2()
所以對於多態我們可以初步總結如下:
指向子類的父類引用由於向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是重載該方法。若子類重寫了父類中的某些方法,在調用該些方法的時候,必定是使用子類中定義的這些方法(動態串連、動態調用)
多態經典案例:
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
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();
// 優先順序由高到低依次為:
// this.clarify(O)、super.clarify(O)、this.clarify((super)O)、super.clarify((super)
// a2.clarify(b),a2是一個引用變數,類別為A,則this為a2,
// b是B的一個的舉例,於是它到類A裡面找clarify(B obj),沒有找到,
// 於是到A的super(超類)找,而A沒有超類,因此轉到第三優先順序this.clarify((super)O),
// this仍然是a2,那裡O為B,(super)O即(super)B即A,因此它到類A裡面找clarify(A obj),
// 類A有那個竅門,但是由於a2引用的是類B的一個的對象,B覆蓋了A的clarify(A
// obj)竅門,因此最終鎖定到類B的clarify(A obj),輸出為"B and A”
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));
}
}
總結:
、多態就是指程式中定義的引用變數所指向的具體類型和通過該引用變數發出的方法調用在編譯時間並不確定,而是在程式運行期間才確定,即一個引用變數倒底會指向哪個類的執行個體對象,該引用變數發出的方法調用到底是哪個類中實現的方法,必須在由程式運行期間才能決定。因為在程式運行時才確定具體的類,這樣,不用修改來源程式代碼,就可以讓引用變數綁定到各種不同的類實現上,從而導致該引用調用的具體方法隨之改變,即不修改程式碼就可以改變程式運行時所綁定的具體代碼,讓程式可以選擇多個運行狀態,這就是多態性。
2、指向子類的父類引用由於向上轉型了,它只能訪問父類中擁有的方法和屬性,而對於子類中存在而父類中不存在的方法,該引用是不能使用的,儘管是重載該方法。若子類重寫了父類中的某些方法,在調用該些方法的時候,必定是使用子類中定義的這些方法(動態串連、動態調用)
3、在繼承鏈中對象方法的調用存在一個優先順序:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。即先查this對象的父類,沒有就重頭再查參數的父類
希望能給各位協助~~~~(>_<)~~~~ !!!!!
java三大特性-----------------------多態