多態

同一個實體同時具有多種形式

在編程語言和類型論中,多態(英語:polymorphism)指為不同數據類型的實體提供統一的介面。多態類型(英語:polymorphic type)可以將自身所支持的操作套用到其它類型的值上。

形式


多態指同一個實體同時具有多種形式。它是面向對象程序設計(OOP)的一個重要特徵。如果一個語言只支持類而不支持多態,只能說明它是基於對象的,而不是面向對象的。C++中的多態性具體體現在運行和編譯兩個方面。運行時多態是動態多態,其具體引用的對象在運行時才能確定。編譯時多態是靜態多態,在編譯時就可以確定對象使用的形式。
多態:同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。在運行時,可以通過指向基類的指針,來調用實現派生類中的方法。
C++中,實現多態有以下方法:虛函數,抽象類,覆蓋,模板(重載和多態無關)。
OC中的多態:不同對象對同一消息的不同響應。子類可以重寫父類的方法
多態就是允許方法重名 參數或返回值可以是父類型傳入或返回。
多態也指生物學中腔腸動物的特殊的生活方式。水螅態與水母態的世代交替現象。

作用


把不同的子類對象都當作父類來看,可以屏蔽不同子類對象之間的差異,寫出通用的代碼,做出通用的編程,以適應需求的不斷變化。
賦值之後,父類型的引用就可以根據當前賦值給它的子對象的特性以不同的方式運作。也就是說,父親的行為像兒子,而不是兒子的行為像父親。
舉個例子:從一個基類中派生,響應一個虛命令,產生不同的結果。
比如從某個基類派生出多個子類,其基類有一個虛方法Tdoit,然後其子類也有這個方法,但行為不同,然後這些子類對象中的任何一個可以賦給其基類對象的引用,或者說將子對象地址賦給基類指針,這樣其基類的對象就可以執行不同的操作了。實際上你是在通過其基類的引用來訪問其子類對象的,你要做的就是一個賦值操作。
使用繼承性的結果就是當創建了一個類的家族,在認識這個類的家族時,就是把子類的對象當作基類的對象,這種認識又叫作upcasting(向上轉型)。這樣認識的重要性在於:我們可以只針對基類寫出一段程序,但它可以適應於這個類的家族,因為編譯器會自動找出合適的對象來執行操作。這種現象又稱為多態性。而實現多態性的手段又叫稱動態綁定(dynamic binding)。
簡單地說,建立一個父類對象的引用,它所指對象可以是這個父類的對象,也可以是它的子類的對象。java中當子類擁有和父類同樣的函數,當通過這個父類對象的引用調用這個函數的時候,調用到的是子類中的函數。

例子


在C++中:
這將顯示:
This is B.
如果把virtual去掉,將顯示:
This is A.
前面的多態通過使用虛函數virtual void foo()來實現。
在java中:
多態,是面向對象的程序設計語言最核心的特徵。多態,意味著一個對象有著多重特徵,可以在特定的情況下,表現不同的狀態,從而對應著不同的屬性和方法。從程序設計的角度而言,多態可以這樣來實現(以java語言為例):
//當然還可以有其他的實現
然後,我們就可以看到多態所展示的特性了:
Parent pa = new Child_A();
pa.simpleCall()則顯然是調用Child_A的方法;
Parent pa = new Child_B();
pa.simpleCall()則是在調用Child_B的方法。所以,我們對於抽象的父類或者介面給出了我們的具體實現后,pa 可以完全不用管實現的細節,只訪問我們定義的方法,就可以了。事實上,這就是多態所起的作用,可以實現控制反轉。這在大量的J2EE輕量級框架中被用到,比如Spring的依賴注入機制。
比如有動物(Animal)之類別(Class),而且由動物繼承出類別雞(Chicken)和類別狗(Dog),並對同一源自類別動物(父類)之一消息有不同的響應,如類別動物有“叫()”之動作,而類別雞會“啼叫()”,類別狗則會“吠叫()”,則稱之為多態。

歷史


1967 年,英國計算機科學家克里斯托弗·斯特雷奇在他的講義合集《編程語言中的基礎概念》中,首次提出了特設多態和參數多態的概念。
1985 年,彼得·瓦格納和盧卡·卡代利在論文中引入了術語“蘊含多態”(英語:inclusion polymorphism)來為子類型和繼承 (計算機科學)建模。。不過子類型和繼承本身在 1967 年就已經在Simula有對應的實現。

參見


子類型
鴨子類型

簡介


計算機程序運行時,相同的消息可能會送給多個不同的類別之對象,而系統可依據對象所屬類別,引發對應類別的方法,而有不同的行為。簡單來說,所謂多態意指相同的消息給予不同的對象會引發不同的動作。
多態也可定義為“一種將不同的特殊行為和單個泛化記號相關聯的能力”。
多態可分為變數多態與函數多態。變數多態是指:基類型的變數(對於C++是引用或指針)可以被賦值基類型對象,也可以被賦值派生類型的對象。函數多態是指,相同的函數調用界面(函數名與實參表),傳送給一個對象變數,可以有不同的行為,這視該對象變數所指向的對象類型而定。因此,變數多態是函數多態的基礎。
多態還可分為:
● 動態多態(dynamic polymorphism):通過類繼承機制和虛函數機制生效於運行期。可以優雅地處理異質對象集合,只要其共同的基類定義了虛函數的介面。也被稱為子類型多態(Subtype polymorphism)或包含多態(inclusion polymorphism)。在面向對象程序設計中,這被直接稱為多態。
● 靜態多態(static polymorphism):模板也允許將不同的特殊行為和單個泛化記號相關聯,由於這種關聯處理於編譯期而非運行期,因此被稱為“靜態”。可以用來實現類型安全、運行高效的同質對象集合操作。C++STL不採用動態多態來實現就是個例子。
● 函數重載(Function Overloading)
● 運算符重載(Operator Overloading)
● 帶變數的宏多態(macro polymorphism)
● 非參數化多態或譯作特設多態(Ad-hoc polymorphism):
● 參數化多態(Parametric polymorphism):把類型作為參數的多態。在面向對象程序設計中,這被稱作泛型編程。
對於C++語言,帶變數的宏和函數重載(function overload)機制也允許將不同的特殊行為和單個泛化記號相關聯。然而,習慣上並不將這種函數多態(function polymorphism)、宏多態(macro polymorphism)展現出來的行為稱為多態(或靜態多態),否則就連C語言也具有宏多態了。談及多態時,默認就是指動態多態,而靜態多態則是指基於模板的多態。