java多態的理解

首先要先知道什麼是多態,多態的概念
函數

1.多態的定義:指容許不一樣類的對象對同一消息作出響應。即同一消息能夠根據發送對象的不一樣而採用多種不一樣的行爲方式。(發送消息就是函數調用)字體

2.多態的做用:消除類型間的耦合。
flex

再說一下三大特性:封裝、繼承、多態。封裝和繼承幾乎就是爲多態服務的。這個必定要記住!this

多態存在的三個條件:spa

  1. 要有繼承
    設計

  2. 要有重寫,也就是覆蓋,這裏有些剛學的人會誤解方法重寫和重載。這個必定要弄明白orm

    a.重寫必須繼承,重載不用。
    b.重寫的方法名,參數數目相同,參數類型兼容,重載的方法名相同,參數列表不一樣。
    c.重寫的方法修飾符大於等於父類的方法,重載和修飾符無關。
    d.重寫不能夠拋出父類沒有拋出的通常異常,能夠拋出運行時異常
    對象

  3. 父類引用指向子類對象繼承

Java中多態的實現方式:接口實現,繼承父類進行方法重寫,同一個類中進行方法重載。接口

多態分爲兩種:

  1. 編譯時多態:方法重載

  2. 運行時多態:JAVA運行時系統根據調用該方法的實例的類型來決定選擇調用哪一個方法則被稱爲運行時多態。(咱們平時說得多的事運行時多態,因此多態主要也是指運行時多態)

最後再說一下多態的好處:

1.可替換性(substitutability)。多態對已存在代碼具備可替換性。例如,多態對圓Circle類工做,對其餘任何圓形幾何體,如圓環,也一樣工做。

2.可擴充性(extensibility)。多態對代碼具備可擴充性。增長新的子類不影響已存在類的多態性、繼承性,以及其餘特性的運行和操做。實際上新加子類更容易得到多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。

3.接口性(interface-ability)。多態是超類經過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。如圖8.3 所示。圖中超類Shape規定了兩個實現多態的接口方法,computeArea()以及computeVolume()。子類,如Circle和Sphere爲了實現多態,完善或者覆蓋這兩個接口方法。

4.靈活性(flexibility)。它在應用中體現了靈活多樣的操做,提升了使用效率。

5.簡化性(simplicity)。多態簡化對應用軟件的代碼編寫和修改過程,尤爲在處理大量對象的運算和操做時,這個特色尤其突出和重要。

這裏加上個例子來複習一下多態的運用

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 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));     ⑨   

(三)答

              ①   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

(四)分析

        ①②③比較好理解,通常不會出錯。④⑤就有點糊塗了,爲何輸出的不是"B and B」呢?!!先來回顧一下多態性。

        運行時多態性是面向對象程序設計代碼重用的一個最強大機制,動態性的概念也能夠被說成「一個接口,多個方法」。Java實現運行時多態性的基礎是動態方法調度,它是一種在運行時而不是在編譯期調用重載方法的機制。

        方法的重寫Overriding和重載Overloading是Java多態性的不一樣表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。若是在子類中定義某方法與其父類有相同的名稱和參數,咱們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被「屏蔽」了。若是在一個類中定義了多個同名的方法,它們或有不一樣的參數個數或有不一樣的參數類型,則稱爲方法的重載(Overloading)。Overloaded的方法是能夠改變返回值的類型但同時參數列表也得不一樣。

        當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,可是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。 (可是若是強制把超類轉換成子類的話,就能夠調用子類中新添加而超類沒有的方法了。)

        好了,先溫習到這裏,言歸正傳!實際上這裏涉及方法調用的優先問題 ,優先級由高到低依次爲:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。讓咱們來看看它是怎麼工做的。

        好比④,a2.show(b),a2是一個引用變量,類型爲A,則this爲a2,b是B的一個實例,因而它到類A裏面找show(B obj)方法,沒有找到,因而到A的super(超類)找,而A沒有超類,所以轉到第三優先級this.show((super)O),this仍然是a2,這裏O爲B,(super)O即(super)B即A,所以它到類A裏面找show(A obj)的方法,類A有這個方法,可是因爲a2引用的是類B的一個對象,B覆蓋了A的show(A obj)方法,所以最終鎖定到類B的show(A obj),輸出爲"B and A」。

        再好比⑧,b.show(c),b是一個引用變量,類型爲B,則this爲b,c是C的一個實例,因而它到類B找show(C obj)方法,沒有找到,轉而到B的超類A裏面找,A裏面也沒有,所以也轉到第三優先級this.show((super)O),this爲b,O爲C,(super)O即(super)C即B,所以它到B裏面找show(B obj)方法,找到了,因爲b引用的是類B的一個對象,所以直接鎖定到類B的show(B obj),輸出爲"B and B」。

        按照上面的方法,能夠正確獲得其餘的結果。

        問題還要繼續,如今咱們再來看上面的分析過程是怎麼體現出藍色字體那句話的內涵的。它說:當超類對象引用變量引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,可是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。仍是拿a2.show(b)來講吧。

        a2是一個引用變量,類型爲A,它引用的是B的一個對象,所以這句話的意思是由B來決定調用的是哪一個方法。所以應該調用B的show(B obj)從而輸出"B and B」纔對。可是爲何跟前面的分析獲得的結果不相符呢?!問題在於咱們不要忽略了藍色字體的後半部分,那裏特別指明:這個被調用的方法必須是在超類中定義過的,也就是被子類覆蓋的方法。B裏面的show(B obj)在超類A中有定義嗎?沒有!那就更談不上被覆蓋了。實際上這句話隱藏了一條信息:它仍然是按照方法調用的優先級來肯定的。它在類A中找到了show(A obj),若是子類B沒有覆蓋show(A obj)方法,那麼它就調用A的show(A obj)(因爲B繼承A,雖然沒有覆蓋這個方法,但從超類A那裏繼承了這個方法,從某種意義上說,仍是由B肯定調用的方法,只是方法是在A中實現而已);如今子類B覆蓋了show(A obj),所以它最終鎖定到B的show(A obj)。這就是那句話的意義所在。

相關文章
相關標籤/搜索