此为历史版本和 IPFS 入口查阅区,回到作品页
ChunYeung
IPFS 指纹 这是什么

作品指纹

什麼是OO?物件導向與多型

ChunYeung
·
·
這次我們要討論的是多型 (Polymorphism)。多型可能是最難以一些簡單言語加以解釋的概念,請各位在看下文時,多加思考在什麼的情境下,我們適合使用多型?

按照慣例,先上維基百科,讓我們來看看物件導向中的多型是指什麼 ?

多型指為不同資料類型的實體提供統一的介面。(撰自: 維基百科)

嗯嗯,這真是非常簡短且精闢定義,只是還是看不懂而已( ╯′ — ′)╯ ┻┻

讓我繼續以杯子為例子,介紹什麼是多型吧!

首先,繼承是多型能夠實現的必要條件 (可參考物件導向與繼承 ),而多型就是原有的類別提供一個上層介面抽象類別,而目的是為了消除了類別與類別之間的耦合性,使程式更容易維護與擴充

這就需要先了解什麼是介面與抽象層,為此我特意寫了篇文章介紹介面與抽象層的文章。 (物件導向中的介面與抽象類別是什麼?)

有了對介面與抽象層的了解後,我們只需要一點例子,大家就可以了解什麼是多型以及使用的時機。

abstract Class Cup {
    abstract protected String getUse();
    abstract protected int getPrice();
}
Class TeaCup extend Cup {
    
    protected String getUse(){
        return 'for tea';
    }
    
    protected int getPrice(){
        return 50;
    }
}
Class CoffeeCup extend Cup {
    
    protected String getUse(){
        return 'for coffee';
    }
    
    protected int getPrice(){
        return 130;
    }
}

如果現在我們有一個分析杯子的程式,我們可能會分別需要兩個分析不同杯子的 function,如下:

public String analysisTeaCup(TeaCup teaCup) {
    if (teaCup.getUse() == 'for tea') {
        return 'cup for tea';
    }else{
        return 'Not Tea Cup';
    }
}
public String analysisCoffeeCup(CoffeeCup coffeeCup) {
    if (coffeeCup.getUse() == 'for coffee') {
        return 'cup for coffee';
    }else{
        return 'Not Coffee Cup';
    }
}

但是我們可以運用多型來為我們多個類似的 function 做重構,如下:

public String analysisCup(Cup cup) {
    if (cup.getUse() == 'for tea') {
        return 'cup for tea';
    }else if (cup.getUse() == 'for coffee'){
        return 'cup for coffee';
    }else{
        return 'Not Tea or Coffee Cup';
    }
}
TeaCup teaCup = new TeaCup();
analysisCup(teaCup);   //'cup for tea'
CoffeeCup coffeeCup = new CoffeeCup();
analysisCup(coffeeCup);   //'cup for coffee'

在上例中,我們使用抽象的 Cup 來作為 function 的參數,而不是分開兩個類別 (TeaCup, CoffeeCup) 來作為參數,所以我們只需要分別把繼承自 Cup 的類別的 Object 注入到 analysisCup() 中,就可以用同一個 function 來進行判斷。

這就是多型的力量,若然今天我們擁有的相似的類別有 30 個時,如不同牌子的汽車,我們絕對不希望為類似的商業邏輯創造分別 30 個 function,我們可以以多型為理念來創造一個通用的 function 給所有汽車類別使用。

同理地,我們也可以使用 interface 來作為多型的原材料,如下:

interface USB {    
    public void execute();    
    public void stop();
}

Class Mouse implements USB {    
    private String state = 'stop';
    private int countClick = 0;    
   
    public void execute() {
        this.state = "start";
    }    
    public void stop() {
        this.state = "stop";
    }    
    private void countClicking() {
        this.countClick += 1
    }
}

Class TestMouse
{
    USB mouse = new Mouse();

    public void startUSB(USB mouse){
        if (mouse.state == 'stop') {
            mouse.execute();
        }
    }
}

介面也可以使用在多型中,以介面為注入的類別,只要乎合介面,就可以被 function 所使用。還記得介面中的方法必須被實作這條規則嗎?當我們的 function 是想透過必須被實作的方法來作判斷時,以介面為多型就會變得超級好用!


至此,OO 三本柱,「封裝、繼承、多型」,我們已經全部介紹完畢,什麼是 OO 系列亦同時告一段落了,希望各位能時時思考 OO 的原則,我們在設計程式時又該如何去應用,這會是程式設計進步的不二法門。

CC BY-NC-ND 2.0 授权