java面向對象三大特征即為:繼承封裝多態。而多態需要三大必要條件。分別是:繼承、方法重寫、父類引用指向子類對象。我們先一個一個來理解。 1、首先是繼承和重寫。這個很簡單。因為多態就是建立在不同的重寫之上的。也就是說多態就是在使用著一個方法的不同重寫。而重寫又是依賴著繼承關係。 2、這個父類引用指向 ...
java面向對象三大特征即為:繼承封裝多態。而多態需要三大必要條件。分別是:繼承、方法重寫、父類引用指向子類對象。我們先一個一個來理解。
1、首先是繼承和重寫。這個很簡單。因為多態就是建立在不同的重寫之上的。也就是說多態就是在使用著一個方法的不同重寫。而重寫又是依賴著繼承關係。
2、這個父類引用指向子類對象。
首先先上代碼示例。
public class Animal { public void Shout(){ System.out.println("叫叫叫"); } public void Hi(){ System.out.println("打招呼"); } } class Dog extends Animal{ public void Shout(){ System.out.println("汪汪汪"); } public void seeHouse(){ System.out.println("看家"); } }class Cat extends Animal{ public void Shout(){ System.out.println("喵喵喵"); } } class goose extends Animal{ public void Shout(){ System.out.println("嘎嘎嘎"); } }
public class TestPolym { public static void main(String[] args) { AnimalShout(new Dog()); AnimalShout(new goose()); } static void AnimalShout(Animal animal){ animal.Shout(); } }
在如上代碼中,Animal類是作為dog、cat、goose的父類。而TestPolym則是用於實現多態
先解釋下父類引用指向子類對象:在TestPolym類中的AnimalShout方法中,接收著Animal類的對象。這就是父類的引用;
指向子類對象則是看這一行:
AnimalShout(new Dog());
這裡其實與AnimalShout方法放在一起可以理解為:
Animal animal = new Dog();
其實這一行打出來基本就可以理解個七七八八。這句話就是定義了一個對象 animal 然後將其實例化成 類型為 Animal 的Dog()。因為Dog、Cat這些是Animal的子類,所以類型 Animal >= Dog、Cat......這些子類。所以首先指向子類是成立的。
其次在 Animal animal = new Dog(); 這個構造器真實的類型為Dog,但是! 編譯器在看animal這個對象的時候,只會將他識別為Animal類型。而這行代碼成立的最重要的原因是:Dog是Animal的一個子類,並且Dog類總是小於等於Animal類。然後我們看一下我們在使用什麼方法。這個方法是Shout。是由Animal重寫而來。因此在調用由Dog類重寫Animal類的方法如此代碼中的Shout方法時,此語句成立。
反之,使用此語句去運行不是由Animal類中的方法重寫而來的方法時,此語句會報錯。例如用這一行去調用seeHouse時
編譯器會紅,並且建議你在Animal中創建這樣一個方法,那我們去創建一下。之後就會發現,Animal和Dog兩個類中都有Hi方法了,又變成重寫了!而且程式也能跑的通了。所以本質上還是Animal類包含(抽象一點的)Dog類。
那麼我就是想在不在父類中創建這方法,並且還想通過animal類去運行seeHouse呢?這時就有了向上轉型和向下轉型這個概念。其中向上轉型其實就是Animal animal = new Dog()這一過程。而向下轉型則是將 animal 這個對象,強制轉換成 Dog類型的過程。
通過如圖的方法就可以實現我們的要求。
但是這其實只是錶面的美好(指編譯成功),事實上有些時候會出現報錯
例如我在Cat方法里新建一個CatEat方法。我想用同樣的方法進行強制類型轉換。編譯並沒有問題,但是卻會報錯
報錯表明Dog無法強制轉換為Cat。這時候回想到上面所說的: animal 對象實際上是Dog類型,而編譯器只是將他看做Animal類型。Dog 和 Cat並無繼承關係,所以不可以~
之後我們加個判斷語句判斷一下這Cat類是否跟animal的類型一樣即可~(使用instanceof語句)