java面向物件(下)-- 多型
多型概述
在設計一個方法時,通常希望該方法具備一定的通用性。例如要實現一個動物叫的方法,由於每種動物的叫聲是不同的,因此可以在方法中接收一個動物型別的引數,當傳入貓類物件時就發出貓類的叫聲,傳入犬類物件時就發出犬類的叫聲。在同一個方法中,這種由於引數型別不同而導致執行結果各異的現象就是多型。
在java中為了實現多型,允許使用一個父類型別的變數來引用一個子類型別的物件,根據被引用子類物件特徵的不同,得到不同的允許結果。
方法的過載和方法的重寫都是java多型性的不同表現,二者一個是編譯時的多型,一個是執行時的多型,當然二者的區別並不侷限如此,這裡就不一一贅述。
多型存在的三個必要條件
- 繼承
- 重寫
- 父類引用指向子類物件
以下是一個多型例項的演示,詳細說明請看註釋:
1 //定義了介面Animal 2 interface Animal { 3 //定義抽象方法 4 void shout(); 5 } 6 //定義了Cat類並實現了Animal介面 7 class Cat implements Animal{ 8 //實現shou()方法 9 public void shout() { 10 System.out.println("喵喵喵....."); 11 } 12 } 13 //定義了Dog類並實現了Animal介面14 class Dog implements Animal{ 15 //實現shout()方法 16 public void shout() { 17 System.out.println("汪汪汪....."); 18 } 19 } 20 //定義測試類 21 class Example { 22 //定義靜態的animalShout()方法,接收一個Animal型別的引數 23 public static void animalShout(Animal an){ 24 an.shout(); 25 } 26 publicstatic void main(String[] args) { 27 Animal an1 = new Cat(); //建立Cat物件,使用Animal型別的變數an1來引用 28 Animal an2 = new Dog(); //建立Dog物件,使用Animal型別的變數an2來引用 29 animalShout(an1); //呼叫animalShout()方法,將an1作為引數插入 30 animalShout(an2); //呼叫animalShout()方法,將an2作為引數插入 31 } 32 }
執行結果:
多型不僅解決了方法同名的問題,而且還使程式變得更加靈活,從而有效地提高程式的可擴充套件性和可維護性。
多型的優點
-
1. 消除型別之間的耦合關係
-
2. 可替換性
-
3. 可擴充性
-
4. 介面性
-
5. 靈活性
-
6. 簡化性
物件的型別轉換
在多型的學習中,涉及到將子類物件當做父類型別使用的情況,例如上面的:
將子類物件當做父類使用時不需要任何顯示地宣告,但此時不能通過父類變數去呼叫子類中的某些方法。
1 //定義了介面Animal 2 interface Animal { 3 //定義抽象方法 4 void shout(); 5 } 6 //定義了Cat類並實現了Animal介面 7 class Cat implements Animal{ 8 //實現shout()方法 9 public void shout() { 10 System.out.println("喵喵喵....."); 11 } 12 //定義sleep()方法 13 void sleep(){ 14 System.out.println("貓在睡覺...."); 15 } 16 } 17 18 //定義測試類 19 class Example { 20 //定義靜態的animalShout()方法,接收一個Animal型別的引數 21 public static void animalShout(Animal animal){ 22 animal.shout();//呼叫傳入引數animal的shout()方法 23 animal.sleep();//呼叫傳入引數animal的sleep()方法 24 25 } 26 public static void main(String[] args) { 27 Cat cat = new Cat(); //建立Cat類的例項化物件 28 animalShout(cat);//呼叫animalShout()方法,將cat作為引數傳入 29 30 } 31 }
執行結果:
在main方法中,呼叫animalShout()方法時傳入了引數Cat型別的物件,而方法的引數型別為Animal型別,這便將Cat物件當做父類Animal型別使用,當編譯器編譯時,發現Animal類中沒有定義sleep()方法,從而出現錯誤,提示找不到sleep()方法。
解決方法:通過強制型別轉換將Animal型別的變數強轉為Cat型別
執行結果:
將傳入的物件有Animal型別轉換為Cat型別後,程式可以成功呼叫shout()方法和sleep()方法。
需要注意的是,在進行型別轉換時也可能出現錯誤,例如在animalShout()方法時傳入一個Dog型別的物件,這時進行強制型別轉換就會出現錯誤。
1 //定義了介面Animal 2 interface Animal { 3 //定義抽象方法 4 void shout(); 5 } 6 //定義了Cat類並實現了Animal介面 7 class Cat implements Animal{ 8 //實現shout()方法 9 public void shout() { 10 System.out.println("喵喵喵....."); 11 } 12 //定義sleep()方法 13 void sleep(){ 14 System.out.println("貓在睡覺...."); 15 } 16 } 17 //定義了Dog類並實現了Animal介面 18 class Dog implements Animal{ 19 //實現shou()方法 20 public void shout() { 21 System.out.println("汪汪汪....."); 22 } 23 } 24 //定義測試類 25 class Example { 26 //定義靜態的animalShout()方法,接收一個Animal型別的引數 27 public static void animalShout(Animal animal){ 28 Cat cat =(Cat) animal;//將animal型別強轉為Cat型別 29 cat.shout();//呼叫cat的shout()方法 30 cat.sleep();//呼叫cat的sleep()方法 31 32 } 33 public static void main(String[] args) { 34 Dog dog = new Dog(); //建立Dog類的例項化物件 35 animalShout(dog);//呼叫animalShout()方法,將cat作為引數傳入 36 37 } 38 }
執行結果:
在呼叫animalShout()方法時,傳入一個Dog物件,在強制型別轉換時,Animal型別的變數無法強轉為Cat型別。
針對這種情況,java提供了一個關鍵字instanceof,它可以判斷一個物件是否為某個類(或介面)的例項或者子類例項,語法格式如下:
物件(或者物件引用變數) instanceof 類(或介面)
接下來對animalShout()方法進行修改
執行結果:
使用instanceof關鍵字判斷animalShout()方法中傳入的物件是否為Cat型別,如果是Cat型別就進行強制型別轉換,否則就會列印“this animal is not a cat”。
ps:個人學習筆記!!!