多型 Polymorphism
是借用了生物學的概念,代表著同一個物種可以有不同的型態、特徵。在物件導向的設計當中,就可以用父類別提供的方法呼叫,但各個子類別可以有不同的運算方式與結果。
再把水果家族請出來當例子吧。
如果我們分別已經建好四個類別與繼承關係如下:
// 水果 Fruits
public class Fruits {
public void eat(){
System.out.println("eating fruit...");
}
//...
}
// 葡萄 Grape
public class Grape extends Fruits {
public void eat(){
System.out.println("eating grape...");
}
//...
}
// 西瓜 Watermelon
public class Watermelon extends Fruits {
public void eat(){
System.out.println("eating watermelon...");
}
//...
}
// 檸檬 Lemon
public class Lemon extends Fruits {
public void eat(){
System.out.println("eating lemon...");
}
//...
}
父與子類別有一個特性是「可以用父類別作為資料型別來宣告子類別」,也就是:
Fruits fruits = new Fruits();
Fruits grape = new Grape();
Fruits watermelon = new Watermelon();
Fruits lemon = new Lemon();
// 無論哪種水果都可以當作 Fruits 類
然而,雖然全部物件都宣告為 Fruits,但如果我們調用同一個方法 eat():
fruits.eat();
grape.eat();
watermelon.eat();
lemon.eat();
// eating fruit...
// eating grape...
// eating watermelon...
// eating lemon...
我們會發現到 grape, watermelon 與 lemon 調用的都是各自的 eat() 方法,而非 fruits 的 eat() 方法,這就是多型的概念「同一個類別但有不同的型態與行為」。
那多型實際上會帶來什麼好處呢?
第一個是可以把不同的類別放到同一個 Array, ArrayList …等。
先前有提到 Array, ArrayList在宣告時需指定元素的資料類別,所以不同類別無法放在同一個 Array, ArrayList 中。
// 假設一個裝 Grape 的 ArrayList
ArrayList\<Grape> basket = new ArrayList<>();
basket.add(new Grape());
// 可以放入 Grape
basket.add(new Lemon());
// 但無法放入其他的類別
// java: incompatible types: Lemon cannot be converted to Grape
// 如果改用父類別 Fruits 作為資料型別
ArrayList<Fruits> basket = new ArrayList<>();
basket.add(new Grape());
basket.add(new Lemon());
basket.add(new Watermelon());
// 就可以把所有子類別都放到同一個 ArrayList 中
再來,如果子類別與父類別都有定義同一個方法,那定義一個操作父類別的方法就可以操作所有子類別
// 如果定義一個 eatFruits 的方法,可以操作 Fruits 物件
public void eatFruits(Fruits fruit){
fruit.eat();
}
Fruits fruits = new Fruits();
Grape grape = new Grape();
Watermelon watermelon = new Watermelon();
Lemon lemon = new Lemon();
// fruits 子類別的物件都可以當成參數使用
eatFruits(fruits)
eatFruits(grape)
eatFruits(watermelon)
eatFruits(lemon)
// eating fruit...
// eating grape...
// eating watermelon...
// eating lemon...