天天看點

Java基礎00-多态19

Java基礎00-多态191. 多态

多态

Java基礎00-多态19

代碼示例:

動物類:

貓類:

多态的前提有繼承/實作關系,是以貓類要繼承動物類。

多态的前提要有方法重寫,是以要重寫父類的eat()方法。

實作類:

要有父類引用指向子類對象

這樣就滿足了多态的前提,這樣的現象就稱之為多态。

通路成員變量的特點:

    直接通過對象名稱通路成員變量:看等号左邊是誰,優先用誰,沒有則向上找。

    間接通過成員方法通路成員變量:看該方法屬于誰,優先用誰,沒有則向上找。

通路成員方法的特點:

    看new的是誰,就優先用誰,沒有則向上找。

Java基礎00-多态19

貓類:

繼承了動物類,并重寫的父類的eat()方法

測試類:

a.age調用可以使用,但是a.weight調用不可以使用,

因為,雖熱記憶體中指向的是子類new Cat(),但是外界看到的是Animal a,通過多态的方式在通路成員變量的時候它的編譯要看左邊(父類),要看左邊(父類)中有沒有,有就可以調用,沒有就不可以調用。

Java基礎00-多态19

接下來運作測試類:

通過多态的形式,去通路成員變量,其實是通路左邊(父類)中的,是以,通過多态的形式,通路成員變量,它的編譯看右邊,運作也看右邊。

Java基礎00-多态19

接下來調用成員方法:

調用a.eat()方法成功,a.playGame()失敗,

可見調用成員方法和變量是一樣的,編譯也要看左邊(父類),右邊有可以通過,沒有就不可以。

Java基礎00-多态19

運作測試類:

運作的是重寫後的方法,由此可見

通過多态的方式,調用成員變方法看的是右邊(子類),運作看右邊

Java基礎00-多态19
Java基礎00-多态19

類目錄:

Java基礎00-多态19
Java基礎00-多态19

貓類繼承了動物類并重寫了它的eat()方法。

Java基礎00-多态19

動物操作類:

它的成員方法的形成類型是Cat。

Java基礎00-多态19
Java基礎00-多态19

運作測試類并調用操作類的方法:

Java基礎00-多态19

運作:

ao.useAnimal©,解析:

調用ao(操作類)中的useAnimal成員方法,

useAnimal方法的形參類型是Cat(貓類),

是以将main方法中的Cat c(指向的就是new Cat())(貓類)放入形參中,此時的形參相當于:Cat c = new Cat();

Java基礎00-多态19

c.eat()方法調用貓類的eat方法,

輸出“貓吃魚”。

Java基礎00-多态19

再加一個狗類型:

和上面的一樣,先建立一個狗類,再在操作類中添加一個新的useAnimal方法這次的形參類型是狗類,調用的是狗類的eat方法。

Java基礎00-多态19
Java基礎00-多态19

這樣的方法明顯比較麻煩,如果要建立多個動物就要重複上面的每一個步驟,

是以我們運用多态。

修改操作類:

将useAnimal方法中的形參變為Animal(動物類),

因為不管貓還是狗,它們都繼承Animal(動物類),

是以我們完全可以将Animal(動物類)作為形參。

Java基礎00-多态19

接着運作測試類:

Java基礎00-多态19

運作結果:

Java基礎00-多态19

運作結果和以前一樣,解析:

以Cat(貓)為例,

ao.useAnimal©,

調用ao(AnimalOperator)的useAnimal方法,

useAnimal方法的形參類型是Animal(動物類),Cat(貓)類的父類也是Animal(動物類),

是以完全可以将Cat c(指向new Cat())指派給Animal(動物類),這樣就變成了,Animal a = new Cat();

Java基礎00-多态19

這樣就形成了多态,多态調用成員方法時,編譯看左邊,運作看右邊,

是以我們就是輸出“貓吃魚”

這樣利用多态就可以省去多個步驟,建立一個useAnimal方法即可。

但是這樣不可以調用子類的特有方法,因為編譯看左邊(父類)。

Java基礎00-多态19
Java基礎00-多态19
Java基礎00-多态19
Java基礎00-多态19

向上轉型:

父類引用指向子類對象,子類對象指派給父類引用

Java基礎00-多态19
Java基礎00-多态19

但是通過向上轉型的方法,通路不了子類特有的方法。

Java基礎00-多态19

是以要用到向下轉型

父類引用a轉為子類對象Cat,指派給Cat

Java基礎00-多态19

運作:

Java基礎00-多态19
Java基礎00-多态19

從main方法開始執行,加載到棧記憶體

Java基礎00-多态19

Animal a加載到棧記憶體

Java基礎00-多态19

在堆記憶體中new一片空間(001),Cat繼承了Animal,是以将位址001指派給Animal a。

這也叫向上轉型

Java基礎00-多态19

多态中執行方法,編譯看左邊,執行看右邊,将Cat類加載到棧記憶體中,調用eat方法,輸出“貓吃魚”。

調用完畢後從棧記憶體消失

Java基礎00-多态19

執行Cat c = (Cat) a;,将Cat c加載到棧記憶體中

Java基礎00-多态19

a指向的是堆記憶體中的001,而001就是Cat,是以001完全可以指派給Cat

這就是向下轉型

Java基礎00-多态19

c指向位址001(Cat),是以可以調用Cat中的方法。

Java基礎00-多态19

執行a = new Dog();,先在堆記憶體中new一片空間002,Dog也繼承了Animal,是以也可以指派給a,這時a的位址值變了002。

Java基礎00-多态19

執行a.eat():,調用方法執行看右邊,進入Dog類執行eat()方法,輸出“狗吃骨頭”。

方法執行結束從棧記憶體消失。

Java基礎00-多态19

Cat cc = (Cat) a;,将Cat cc加載到棧記憶體,(Cat) a,a的位址值是002,002對應的是Dog方法。

Java基礎00-多态19

雖然貓和狗都繼承自Animal但是兩者是沒有任何關系的,是以他們互相之間是不能進行轉換的。

Java基礎00-多态19

是以這個地方是錯誤的,如果強制執行就會報錯,類型轉換異常。

Java基礎00-多态19
Java基礎00-多态19
Java基礎00-多态19