1. 程式人生 > 實用技巧 >java面向物件(下)-- 多型

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 public
static 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:個人學習筆記!!!