# 多型基本概念

多型表示利用父類別提供的方法呼叫,卻可以獲得子類別特有的行為。

class Animal{
    void move(){
        System.out.println("Animal moves!!!");
    }
}
class Dog extends Animal{
    void move(){
        System.out.println("Dog run!!!");
    }
}
class Bird extends Animal{
    void move(){
        System.out.println("Bird fly!!");
    }
}
class App{
    public static void main(String[] args){
        Animal animal = new Animal();
        Animal dog = new Dog();
        Animal bird = new Bird();
        animal.move();
        dog.move();
        bird.move();
    }
}

變數 animalAnimal 的構建子宣告,這很符合常理。
變數 dog 就稍顯奇怪,以 Dog() 來初始化竟然可以用 Animal 來定義型態!
這是因為繼承的關係, Dog is Animal 。所以, Dog() 建構出來的物件會擁有 Dog 類別的成員,我們僅僅只是把這個物件當作 Animal 在看。

Animal moves!!!
Dog run!!!
Bird fly!!!

雖然三者皆是由 Animal 做形態上的宣告,也都使用了 move() 作為方法,
但他實際上的本質不一,這就是多型的一種基本範例。

這樣的設計方式可以降低方法定義對類別的依賴,使用一個制定好的介面,利用該介面來操作不同的物件,增加程式的彈性及可維護性,設計上也比較有架構。

如果我們沒有多型的話,就必須針對不同物件設置不同的方法進行處理。

void AnimalMove(Animal animal){
    animal.move();
}
void DogMove(Dog dog){
    dog.move();
}
void BirdMove(Bird bird){
    bird.move();
}

# 隱性轉型

來看個簡單的範例:

class App {
    public static void main(String[] args) {
        Animal a = new Animal();
        Dog d = new Dog();
        Bird b = new Bird();
        moveAnimal(a);
        moveAnimal(d);
        moveAnimal(b);
    }    
    static void moveAnimal(Animal ani){
        ani.move();
    }
}

在上面程式中,我們定義了 moveAnimal(Animal animal) 的方法,他會接受一個 Animal 參數進來。同時的,Java 會幫你進行型態轉換,子類別必定擁有母類別的所有屬性、所有方法,所以子類別一定可以轉型為母類別,而不會出錯。

Dog d = new Dog();
Animal a1 = d;  // Java 幫你作了型態轉換,但你看不到,等價於下行
Animal a2 = (Animal)d;  // 自己寫是一樣的
moveAnimal(d); // 等價於下行
moveAnimal((Animal)d);

因為這個機制,所以搭配多型的設計方法,程式撰寫上變得非常便利。

# 轉型失敗

以繼承來說,子類別是母類別的『延伸』擁有母類別的所有欄位、所有方法。
所以,子類別可以轉換成母類別。但,反之亦然嗎?

Animal ani = new Animal();
Dog d = (Dog)ani;  // 母類別強制轉型為子類別
Exception in thread "main" java.lang.ClassCastException:
Animal cannot be cast to Dog

當然的,執行的時候發生了錯誤,產生 ClassCastExeption 例外。

更新於 閱讀次數

用實際行動犒賞爆肝的我😀

Zrn Ye LinePay

LinePay