什麼是OO?物件導向與多型
這次我們要討論的是多型 (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 的原則,我們在設計程式時又該如何去應用,這會是程式設計進步的不二法門。