簡介
一個方法所屬的對象叫做方法的接收者,方法的接收者與方法的參量統稱為方法的宗量。根據分派可以基於多少種宗 量,可以將面向對象的語言分為單分派語言和多分派語言。單分派語言根據一個宗量的類型進行對方法的選擇,多分派語言根據多於一個宗量的類型對方法進行選擇。Java是單分派語言,因為它動態分派僅僅會考慮到方法的接收者類型,同時又是靜態的多分派語言,因為它對重載方法的分派會考慮到方法的接收者類型以及方法的所有參量的類型。 在一個支持動態單分派的語言裡(如Java),有兩個條件決定了一個請求會調用哪一個操作,一是請求的名字,二是接 收者的真實類型,單分派限制了方法的選擇過程,使得只有一個宗量可以被考慮到,這個宗量通常就是方法的接收者 。
簡單來說,單分派是指調用一個對象的方法僅由對象的類型決定。多分派是指調用一個對象的方法不僅由對象的類型決定,同時還由其他因素決定,比如方法參數的類型等等。
分派
變數被聲明時的類型叫做變數的靜態類型,或叫做明顯類型,而變數所引用的對象的真實類型叫做實際類型,這種根據對象的類型而對方法進行的選擇,就是分派。分派是面向對象的語言所提供的關鍵特性之一。根據對象的類型而對方法進行的選擇,就是分派(Dispatch)。根據分派發生的時期,可以將分派分為兩種,即分派分靜態分派和動態分派。
靜態分派(Static Dispatch) 發生在編譯時期,分派根據靜態類型信息發生。方法重載(Overload)就是靜態分派。即所謂的編譯時多態。
動態分派(Dynamic Dispatch) 發生在運行時期,動態分派動態地置換掉某個方法。面向對象的語言利用動態分派來實現方法置換產生的多態性。即所謂的運行時多態。在有些程式語言中,這種數據類型的區分可以被延後到運行時,例如後綁定(late binding)。分派發生在運行時並依據運行時方法的參數類型,這種方式的分派通常也被稱為多方法(multimethods)。
多態
在程式語言和類型論中,多態(polymorphism)指為不同數據類型的實體提供統一的接口。多態類型(polymorphic type)可以將自身所支持的操作套用到其它類型的值上。
電腦程式運行時,相同的訊息可能會送給多個不同的類別之對象,而系統可依據對象所屬類別,引發對應類別的方法,而有不同的行為。簡單來說,所謂多態意指相同的訊息給予不同的對象會引發不同的動作。
多態也可定義為“一種將不同的特殊行為和單個泛化記號相關聯的能力”。
多態可分為變數多態與函式多態。變數多態是指:基類型的變數(對於C++是引用或指針)可以被賦值基類型對象,也可以被賦值派生類型的對象。函式多態是指,相同的函式調用界面(函式名與實參表),傳送給一個對象變數,可以有不同的行為,這視該對象變數所指向的對象類型而定。因此,變數多態是函式多態的基礎。多態還可分為:
•動態多態(dynamic polymorphism):通過類繼承機制和虛函式機制生效於運行期。可以優雅地處理異質對象集合,只要其共同的基類定義了虛函式的接口。也被稱為子類型多態(Subtype polymorphism)或包含多態(inclusion polymorphism)。在面向對象程式設計中,這被直接稱為多態。
•靜態多態(static polymorphism):模板也允許將不同的特殊行為和單個泛化記號相關聯,由於這種關聯處理於編譯期而非運行期,因此被稱為“靜態”。可以用來實現類型安全、運行高效的同質對象集合操作。C++ STL不採用動態多態來實現就是個例子。
•參數化多態(Parametric polymorphism):把類型作為參數的多態。在面向對象程式設計中,這被稱作泛型編程。
對於C++語言,帶變數的宏和函式重載(function overload)機制也允許將不同的特殊行為和單個泛化記號相關聯。然而,習慣上並不將這種函式多態(function polymorphism)、宏多態(macro polymorphism)展現出來的行為稱為多態(或靜態多態),否則就連C語言也具有宏多態了。談及多態時,默認就是指動態多態,而靜態多態則是指基於模板的多態。
有關術語
參數多態在程式設計語言與類型論中是指聲明與定義函式、複合類型、變數時不指定其具體的類型,而把這部分類型作為參數使用,使得該定義對各種具體類型都適用 。參數化多態使得語言更具表達力,同時保持了完全的靜態類型安全。這被稱為泛型函式、泛型數據類型、泛型變數,形成了泛型編程的基礎。
參數多態名字來源於其發明人克里斯托弗·斯特雷奇,與特設多態(ad hoc polymorphism)相對。特設多態是指一個多態函式有多個不同的實現,依賴於其實參而調用相應版本的函式。因此,特設多態僅支持有限數量的不同類型。
特定多態(ad hoc polymorphism)是程式設計語言的一種多態,多態函式有多個不同的實現,依賴於其實參而調用相應版本的函式。因此,特設多態僅支持有限數量的不同類型。函式重載乃至運算符重載也是特設多態的一種。
特定多態的名字來源於其發明人克里斯托弗·斯特雷奇於1967年8月在哥本哈根的電腦程式設計暑期學校發表了著名論文Fundamental Concepts in Programming Languages中首次提出了參數多態、特設多態、左值、右值等概念。特設多態與參數多態相對。ad hoc在這裡並不是貶義,而是指這類多態並不是類型系統的基本特性,不是像參數多態那樣適用於無窮多的類型,而是針對特定問題的解決方案。
換言之,參數多態對各模板參數的實現,是根據模板的通用(generically)的行為的抽象,即泛型的語義;而特設多態可以針對不同的版本實現完全不同的行為,或曰對於每個不同的模版參數都有單獨的版本來應對。打個比方:假如我們要把原材料切成兩半—
•參數多態:只要能“切”,就用工具來切割它;
•特設多態:根據原材料是鐵還是木頭還是什麼來選擇不同的工具來切。