在網上常常能看到文章講面向對象的三大基本特征"繼承"、"封裝"、"多態",我以為這是坊間流傳的最不靠譜的一個說法。本文先談談其中講到的一個特性:多態。多態是一個跟面向對象完全正交的概念,兩者之間可以說沒有任何必然聯系。當然口說無憑,下面是我經過很長時間查找到的一些來源比較可靠的資料對多態的說法。
最早可查證的關於多態的說法是一篇叫做 Fundamental Concepts in Programming Languages的論文,文中對多態的討論主要是用於實現運算符的重載版本選擇,文中把多態分為兩種: ad-hoc多態和參數多態,ad-hoc多態即指系統根據上下文自己決定如何選擇運算符的行為,比如各種原生的運算符都在此列。參數多態則是根據參數類型選擇。文中對參數多態的解釋則是用了一個頗為"函數式"的例子,根據傳入的函數類型參數的函數簽名來決定返回值類型。
1985年左右的一篇論文On Understanding Types, Data Abstraction, and Polymorphis則詳細地論述總結了多態性的概念,文中給出了多態的分類:
polymorphism(多態)
|-universal
| |- parametric
| - inclusion
-ad-hoc
|- overloading
- coercio
這篇文章對多態的論述比較系統,網上也有pdf版本,有興趣的朋友可以詳細閱讀。(inclusion多態聽起來比較陌生,但是其實它的另一個名稱是subtype Polymorphism,這也是唯一一種跟面向對象相關的多態)
從上面的發展可以看出,多態是一個差不多跟面向對象同時(60年代)誕生的編程概念,有自己獨立的體系結構,並且這個概念非常廣泛地用於很多種編程語言的設計當中。
關於面向對象跟多態的關系,下面一段話用來解釋非常恰當(來自The C++ programming language),
Since both(wintercn注:根據上下文指template和abstract class) allow an algorithm to be expressed once and applied to a variety of types, people sometimes refer to both as polymorphic.
意思是:因為template和abstract class兩種機制都能允許一個算法表達一次而用在多種不同類型當中,所以人們把兩種都稱作多態。後文還講到abstract class提供的是運行時多態,template提供的是編譯時多態。(有趣的是,連面向對象的代表性語言之一C++本身都涉及到了一種跟面向對象毫無關系的多態類型。)
所以事實上,多態並非面向對象的私產,更不是什麼面向對象的基本特征,多態和面向對象的關系是:面向對象中的抽象類,提供了一種運行時多態的實現方式。