在程式語言和型別論中，多型指為不同資料型別的實體提供統一的介面，或使用一個單一的符號來表示多個不同的型別 Polymorphic types are types whose operations are applicable to values of more than one type。 多型的最常見主要類別有： 特設多型：為個體的特定型別的任意集合定義一個共同介面。 引數多型：指定一個或多個型別不靠名字而是靠可以標識任何型別的抽象符號。 子型別（也叫做子型別多型或包含多型）：一個名字指稱很多不同的類的例項，這些類有某個共同的超類 Booch et al 2007 ObjectOriented Analysis and Design with Applications AddisonWesley。 歷史 在 1967 年，英國計算機科學家克里斯托弗斯特雷奇在他的講義合集《》中，首次提出了特設多型和引數多型的概念。特設多型是 ALGOL 68 的特徵，而引數多型是 ML 在 1975 年介入的型別系統的核心特徵 Milner R Morris L Newey M A Logic for Computable Functions with reflexive and polymorphic types Proc Conference on Proving and Improving Programs ArcetSenans 1975。 在 1985 年，和在論文中引入了術語「包含多型」來為子型別和繼承建模，引證 1967 年的 Simula 為子型別和繼承的最早的對應實現。 類別 特設多型 克里斯托弗斯特雷奇選擇術語 特設多型 來指稱一個多型函式可以應用於有不同型別的實際引數上，但是以來它們所應用到的實際引數型別而有不同的表現（也叫做為函式過載或運算子過載）。在這個上下文中術語 特設（ad hoc）不意圖表達貶義，它只是簡單的指出這種多型不是型別系統的基本特徵。在下面的 PascalDelphi 例子中，在檢視 Add 函式的呼叫的時候，它好像通用的工作在各種型別之上，但編譯器對所有意圖和用途都把它們視為完全不同的兩個函式 program Adhoc function Add x y Integer Integer begin Add x y end function Add s t String String begin Add Concat s t end begin Writeln Add 1 2 列印 3 Writeln Add Hello Mammals 列印 Hello Mammals end 在動態型別語言中情況可能更加複雜，因為需要呼叫的正確函式只能在執行時間確定。 隱式型別轉換也被定義為多型的一種形式，叫做 強迫多型。 引數多型 引數多型允許函式或資料型別被一般性的書寫，從而它可以 統一 的處理值而不用依賴於它們的型別 Pierce B C 2002 Types and Programming Languages MIT Press。引數多型是使語言更加有表現力而仍維持完全的靜態型別安全的一種方式。這種函式和資料型別被分別稱為 泛化函式 和 泛化資料型別 從而形成了泛型程式設計的基礎。 例如，可以構造連線兩個列表的一個函式 append，它不關心元素的型別：它可以附加整數的列表、實數的列表、字串的列表等等。設定 型別變數 a 來指定這個列表中元素的型別。接著 append 可以確定型別： forall a a a a 這裡的 a 指示具有型別 a 的元素的列表型別。我們稱對於 a 的所有的值，append 的型別 由 a 引數化。結果的列表必須由相同型別的元素組成。對於應用 append 的每個位置，都要為 a 確定一個值。 引數多型的概念適用於資料型別和函式二者。可以被求值或應用於不同型別的值之上的函式叫做 多型函式。看起來具有泛化型別性質的資料型別（比如具有任意型別的元素的列表）被指認為 多型資料型別，就像根據它來做特殊化的泛化型別那樣。 引數多型在函數語言程式設計之中是普遍的，在這裡它經常被簡稱為 多型。下面的 Haskell 例子展示了引數化列表資料型別和在其上的兩個引數多型函式： data List a Nil Cons a List a length List a Integer length Nil 0 length Cons x xs 1 length xs map a b List a List b map f Nil Nil map f Cons x xs Cons f x map f xs 引數多型在很多面向物件語言中也能獲得到。例如，C 和 D 的模板，和在 C、Delphi 和 Java 中所稱謂的泛型 class ListT class NodeT T elem NodeT next NodeT head int length ListB map FuncA B f ListA xs （和後來的）正式的將這種多型概念發展為對 lambda 演算的擴充套件（叫做多型 lambda 演算或系統 F）。任何引數多型函式都必然在能做什麼上受到限制，工作在資料的形狀而不是它的值之上，這導致了的概念。 子型別 在面向物件程式設計中，計算機程式執行時，相同的訊息可能會送給多個不同的類別之物件，而系統可依據物件所屬類別，引發對應類別的方法，而有不同的行為。簡單來說，所謂多型意指相同的訊息給予不同的物件會引發不同的動作。比如有動物之類別，而且由動物繼承出類別貓和類別狗，並對同一源自類別動物（父類別）之一訊息有不同的響應，如類別動物有「叫」之動作，而類別貓會「喵喵」，類別狗則會「汪汪」，則稱之為多型態。 在下面的這個例子中貓和狗都是動物的子型別。過程 letsHear 接受一個動物，但在傳遞給它一個子型別的時候也能正確工作： abstract class Animal abstract String talk class Cat extends Animal String talk return Meow class Dog extends Animal String talk return Woof static void letsHear final Animal a println atalk static void main String args letsHear new Cat letsHear new Dog 多型可分為變數多型與函式多型。變數多型是指：基型別的變數（對於 C 是引用或指標）可以被賦值基型別物件，也可以被賦值派生型別的物件。函式多型是指，相同的函式呼叫介面（函式名與實參表），傳送給一個物件變數，可以有不同的行為，這視該物件變數所指向的物件型別而定。多型也可定義為 一種將不同的特殊行為和單個泛化記號相關聯的能力，變數多型是函式多型的基礎。 實現角度類別 依據實現時做出的選擇，多型可分為： 動態多型（dynamic polymorphism） 生效於執行期。 靜態多型（static polymorphism）：將不同的特殊行為和單個泛化記號相關聯，由於這種關聯處理於編譯期而非執行期，因此被稱為 靜態。可以用來實現型別安全、執行高效的同質物件集合操作。C STL 不採用動態多型來實現就是個例子。 對於 C 語言，帶變數的宏和函式過載機制也允許將不同的特殊行為和單個泛化記號相關聯。然而，習慣上並不將這種函式多型、宏多型展現出來的行為稱為多型（或靜態多型），否則就連 C 語言也具有宏多型了。談及多型時，預設就是指動態多型，而靜態多型則是指基於模板的多型。 參見 鴨子型別 系統 F 型別類 型別論 虛繼承 參考資料 Category 面向物件的程式設計 Category 泛型程式設計