面向對象三大特性:封裝、繼承和多態。
今天學最後一個特性:多態。
什麼叫多態呢?按照字面意思理解就是多種形態的意思。
還是舉昨天的那個例子:
動物園裡動物都得吃食物,兔子吃胡蘿蔔,貓吃魚,狗吃肉。
同一行為(吃東西),通過不同的事物(兔,貓,狗),可以體現出不同的形態(兔子吃胡蘿蔔,貓吃魚,狗吃肉),這就叫多態。
一、多態的格式
1.格式說明:父類引用指向子類對象。
具體什麼意思呢?
變量有基本數據類型和引用數據類型。
其中引用數據類型又分為:數組,類和接口。
父類類型指的是子類繼承至的父類,或者子類實現的接口。
按照現實裡面的理解就是:一個是親爹一個是乾爹。
2.要存在方法重寫
其中父類引用(也就是圖中的Zoo)在調用方法時,會先看自己有沒有這個方法(eat方法)。
如果沒有eat()方法,編譯會報錯;
如果有這個方法,會執行子類重寫後的方法,
口訣就是:編譯看左邊,運行看右邊
就比如上圖中:zoo.eat()
①編譯會先看左邊,Zoo接口中有沒有eat()方法,有,編譯通過。
②運行結果看右邊,是Rabbit對象,那麼會執行Rabbit中重寫的eat()方法,也就是「兔子吃胡蘿蔔」。
二、多態的好處
既然是面向對象三大特性,那它有啥好處呢?
當父類類型作為方法形式參數時,更能體現出多態的擴展性與便利。
現在要展現動物的eat()方法和sleep()方法。
如果不使用到多態,常規用法,代碼如下:
就是每一個動物都得建立一個對象,並且建立其對象對應的show()方法。
那麼問題來了,動物園裡那麼多動物,每個動物都建一個show()方法,會顯得特別繁瑣。
如果應用到多態的話,就會簡單很多。
代碼如下:
每一個動物就建立對象,但是只需要一個show()方法就可以了。
show()方法參數是父類類型的引用。
這樣無論建立多少個動物對象,只要是子類,都可以將參數傳入這個方法,直接使用。
這就叫代碼的可拓展性,以後無論是刪減哪種動物,或者是添加哪種動物,這個方法都可以使用,不用改變。
三、多態的弊端
多態這麼方便,那它有沒有什麼弊端呢?
是有的。多態不能調用子類的特有方法,需要使用到強制轉換。
兔類中有一個特有的方法jump(),兔類的父接口Zoo中沒有這個方法。
那麼父類引用zoo就不能調用這個特有的方法。
需要使用到強制轉換,也就是(Rabbit)zoo。
格式為:(類型名)變量名。
注意:
上面這段代碼,編譯是沒有問題的,但是運行會報錯。
ClassCastException,中文就是:類轉換異常。
其實很好理解,變量zoo定義的時候,本來是子類dog對象,現在強制轉換成子類Rabbit,自然沒法運行。
為了避免出現類轉換異常,Java提供了一個關鍵字:instanceof,給變量名做類型的校驗。
格式為:變量名 instanceof 類型
如果變量屬於該類型,返回true;如果變量不屬於該類型,返回false。總結: