l

2012年1月27日 星期五

什麼是物件導向(3):Polymorphism

January 26 23:01~January 27 00:23


Polymorphism,中文翻譯成「多型」,說真的這個概念當年Teddy學OO的時候搞了好久才弄懂,後來看了「課本」的定義之後,覺得寫得還滿好的,請參考Object-Oriented Software Engineering: A  Use Case Driven Approach:

Polymorphism means that the sender of a stimulus does not need to know the receiving instance’s class. The receiving instance can belong to an arbitrary class.

再看一下55頁中另一段類似的解釋

If an instance sends a stimulus to another instance, but does not have to be aware of which class the receiving instance belongs to, we say that we have polymorphism.

翻成白話文就是說:一個訊息(message or event or stimulus)的意義是由接收者(接收到這個訊息的物件)來解釋,而不是由訊息發出者(sender)來解釋。所以,在runtime時只要接受者換成不同的物件或是instance,系統的行為就會改變。具有這樣的特性就稱之為polymorphism。還是不懂,對,很正常。不過在看一個活生生的例子鄉民們就應該懂了。

***

Teddy(sender,等一下準備送出信息的物件)走在路上看到前方有兩位名人,分別是「林志玲」與「阿美姐」(等一下準備接收訊息的兩個物件),於是大喊一聲「美女請留步(訊息)」。理論上Teddy期待只有「林志玲」會「回頭」(訊息接收者的行為),沒想到「阿美姐」也回頭了...XD。所以說,一個訊息的解釋是由接收者來決定的,而不是送出者。如果一個系統具有這樣的特性,那麼我們就說這個系統具備多型的行為。

舉個程式的例子:

List<String> list = new LinkedList<String>();

list.add(“This is a book”);

從上面這一行程式來看,我們可以說寫程式的人送了一個add這個訊息給list這個instance。從靜態程式碼來看,鄉民們一定知道list.add(“This is a book”)的行為,但是如果list這個instance不是像上面程式一樣寫死new LinkedList<String>();,而是runtime時傳入的任意符合List介面的某個instance,那麼程式的行為就無法只從靜態的程式碼得知了,而且add(“This is a book”);訊息的解釋也只能看runtime時list instance指到哪一個instance而定。

***

一般常用的靜態型別程式語言例如Java、C#,要做到polymorphism必須透過繼承,不管是implementation inheritance或是interface inheritance。有些動態型別程式語言,如果Teddy沒記錯的話像是Smalltalk(如果有錯請留言或來信幫忙更正),可以不需要靠繼承來達到polymorphism,但是在runtime如果接收者沒有支援某個訊息的話,則是會出現runtime errors。

總之,其實Teddy想講的重點是,這些老外厲害的地方,就是可以用很簡短的句子寫出某些觀念或是名詞的定義。因為除非真正了解所要描述的觀念或是名詞,否則是無法寫出這樣的定義出來。當年Teddy背下這個定義(因為考試會考啊…Orz)到現在都還依稀記得。什麼,你問Teddy記下這些定義有何用 ?Teddy也說不上來,也許哪一天鄉民們去面試不小心考了polymorphism這一題,而鄉民們恰巧看到這篇文章所以把書中的定義給寫了出來,但是主考者可能看不懂...Orz。不過這都不是重點,就以「純欣賞」的角度為能夠寫出這麼精簡定義的作者們拍拍手就好了...XD。

***

友藏內心獨白:這幾天好冷,寫到手都凍僵了。

5 則留言:

  1. 這樣說,不知合不合適?

    多形就是:同一個介面下,於不同實作中定義多型之方法,使得操作不同實作的物件者不用關心是哪個實作實體,只要操作共同之介面就能正確地行為。

    這樣是很實際說到:為什麼要多型這回事
    不過還不夠general....

    或者說,它是種期待,期待發出端只要知道傳送什麼msg,而由接收者來作不同的處理
    以這種特性去作的語言還有一個:Obj C,它幾乎都是用msg去傳遞的,反倒是C++的多型有點綁太多了

    回覆刪除
  2. SUPERSUPERSUPERSUPERSUPERSUPER MAN2012年1月27日 上午1:26

    更直接點講,多形就是希望:使用不同實作之物件時,使用統一的訊息傳遞介面,完全不用操心實作之細節差異
    這和希望把一切細節都包進黑盒子的事,是有著異曲同工之妙,但一個強調:資料細節解藕及資料保護等等,多型則是強調:只要有統一的介面,就不用擔心對於不同實作的操作

    也就是說,把處理判斷交給實作之實體,那麼可以少去switch及主程式與特定class的coupling,此外還能讓符合規格的物件能夠作一模一樣的操作而不用改寫,也就是:
    runtime智慧化處理之模型

    我個人覺得當初想到多型概念的人,大概心裡在想這個吧?:P

    回覆刪除
  3. 有沒有實際的例子, 讓我們看看多型到底有多行?^^

    回覆刪除
  4. Hero為介面,有一個savePrincess的方法
    實作兩種Hero: AsianHero與EuropeanHero
    他們對於『救公主』都各有一套

    今天要拍一個場景,我只要宣告一個Hero出來,至於要是哪一種Hero,我可以有各種考量,也可以當場決定,但不論是AsianHero或是EuropeanHero,都可以成功救出公主。

    大概是這樣。

    回覆刪除
  5. 感謝分享!

    看了文章說明還是沒理解到「意義是由接收者來解釋的」這個概念是什麼意思?

    根據引用的
    「Polymorphism means that the sender of a stimulus does not need to know the receiving instance’s class. The receiving instance can belong to an arbitrary class.」
    或是
    「If an instance sends a stimulus to another instance, but does not have to be aware of which class the receiving instance belongs to, we say that we have polymorphism.」
    都沒有提到 receiving instance 應該是什麼。

    所以白話文中的「是由接收者(接收到這個訊息的物件)來解釋」我就搞不太清楚。

    從原文來看,我理解的比較像是:我前面有一個女生,我只要喊出「美女請留步」,這個女生就會回頭。我不用管他是林志玲或是阿美姐,都可以達到叫前面這個女生回頭的目的。

    如果我需要 "be aware of which class the receiving instance belongs to" ,那就表示說只喊出「美女請留步」不管是林志玲或是阿美姐都不會回頭,我要先知道他是林志玲或是阿美姐之後,針對兩個人個別喊出「志玲姐姐請留步」或是「阿美姐請留步」她們才會回頭。

    回覆刪除