泛型程式設計（英文：generic programming）是程式設計語言的一種風格或範型。泛型允許程式設計師在強型別程式設計語言中編寫程式碼時使用一些以後才指定的型別，在例項化時作為引數指明這些型別。各種程式語言和其編譯器、執行環境對泛型的支援均不同。Ada、Delphi、Eiffel、Java、C、F、Swift 和 Visual Basic NET 稱之為泛型（generics）；ML、Scala 和 Haskell 稱之為引數多型（parametric polymorphism）；C 和 D 稱之為模板。具有廣泛影響的 1994 年版的《Design Patterns》一書稱之為引數化型別（parameterized type）。 泛型的定義及目的 泛型的定義主要有以下兩種： 在程式編碼中一些包含型別引數的型別，也就是說泛型的引數只可以代表 zhhans 類；zhhant 類別；，不能代表個別 zhhans 物件；zhhant 物件；。（這是當今常見的定義） 在程式編碼中一些包含引數的 zhhans 類；zhhant 類別；。其引數可以代表 zhhans 類；zhhant 類別； 或 zhhans 物件；zhhant 物件； 等等。（現在人們大多把這稱作模板） 不論使用哪個定義，泛型的引數在真正使用泛型時都必須作出指明。 一些強型別程式語言支援泛型，其主要目的是加強型別安全及減少 zhhans 類；zhhant 類別； 轉換的次數，但一些支援泛型的程式語言只能達到部份目的。 偽程式碼例子 類 例泛類 T 值 T 設定值 新值 T 值 新值 獲取值 T 返回 值 例方法 1 例物件：例泛類 整數型 例物件 新 例泛類 整數型 例物件。設定值 5 輸出整數 例物件。獲取值 例方法 2 例物件：例泛類 浮點數型 例物件 新 例泛類 浮點數型 例物件。設定值 55 輸出浮點數 例物件。獲取值 在這例子中，例泛 Azh 類；zhhans 類；zhhant 類；zhcn 類；zhtw 類；zhhk 類；zhsg 類；zhmo 類； 是一個泛型，而 T 是一個型別引數。在例泛 Azh 類；zhhans 類；zhhant 類；zhcn 類；zhtw 類；zhhk 類；zhsg 類；zhmo 類； 中沒指明 T 的實際型別，只有例方法 1 和例方法 2 在使用例泛 Azh 類；zhhans 類；zhhant 類；zhcn 類；zhtw 類；zhhk 類；zhsg 類；zhmo 類； 時才加以指明。 執行這例子的例方法 1 將輸出整數 5，而執行例方法 2 將輸出浮點數 55。 一些程式語言的泛型特性 NET 的泛型 NET 泛型的引數只可以代表 zhhans 類；zhhant 類別；，不能代表個別 zhhans 物件；zhhant 物件；。由於 NET 泛型的型別引數之實際型別在執行時均不會被消除，執行速度會因為型別轉換的次數減少而加快。另外，使用 GetType 方法可於程式執行時得知泛型及其型別引數的實際型別，更可以運用反射式程式設計。 using System 定義一個泛型列表類，T 表示型別引數 public class GenericListT private T _items 儲存列表 items 的陣列 private int _count 列表中 items 的計數 建構函式，初始化列表的容量 public GenericList int capacity _items new T capacity _count 0 新增 item 到列表中 public void Add T item if _count _itemsLength _items _count item _count else ConsoleWriteLine List capacity reached 列表容量已滿 根據索引獲取列表中的 item public T GetItem int index if index 0 index _count return _items index else throw new IndexOutOfRangeException Index out of range 索引超出範圍 public class Program public static void Main 建立一個儲存整數的泛型列表 GenericListint intList new GenericListint3 intListAdd 1 intListAdd 2 intListAdd 3 ConsoleWriteLine intListGetItem 1 輸出 2 建立一個儲存字串的泛型列表 GenericListstring stringList new GenericListstring2 stringListAdd Hello stringListAdd World ConsoleWriteLine stringListGetItem 0 輸出 Hello 在上面的例子中展示了一個簡單的泛型列表類 GenericListT，它可以儲存任何型別的資料（由 T 指定）。Program 類中的 Main 方法演示瞭如何使用這個泛型類來儲存和檢索整數和字串。 NET 允許對個別泛型的型別引數進行約束，包括以下幾種形式（假設 T 是泛型的型別引數，C 是一般 zhhans 類；zhhant 類別；、泛類，或是泛型的型別引數）： T 是一個 zhhans 類；zhhant 類別；。 T 是一個值型別。 T 具有無引數的公有建構方法。 T 實現 zhhans 介面；zhhant 介面；I。 T 是 C，或繼承自 C。 Java 的泛型 Java 泛型的引數只可以代表 zhhans 類；zhhant 類別；，不能代表個別 zhhans 物件；zhhant 物件；。由於 Java 泛型的型別引數之實際型別在編譯時會被消除，所以無法在執行時得知其型別引數的型別，而且無法直接使用基本值型別作為泛型型別引數。Java 編譯程式在編譯泛型時會自動加入型別轉換的編碼，故執行速度不會因為使用泛型而加快。 由於執行時會消除泛型的物件例項型別資訊等缺陷經常被人詬病，Java 及 JVM 的開發方面也嘗試解決這個問題，例如：Java 透過在生成位元組碼時新增型別推導輔助資訊，從而可以透過反射介面獲得部分泛型資訊；透過改進泛型在 JVM 的實現，使其支援基本值型別泛型和直接獲得泛型資訊等。 Java 允許對個別泛型的型別引數進行約束，包括以下兩種形式（假設 T 是泛型的型別引數，C 是一般 zhhans 類；zhhant 類別；、泛類，或是泛型的型別引數）： T 實現介面 I。 T 是 C，或繼承自 C。 C 的泛型（模板） C 泛型的引數可以代表 zhhans 類；zhhant 類別； 或個別 zhhans 物件；zhhant 物件；。在一般意義上，C 缺乏對泛型的型別引數進行直接約束的手段，但可利用 SFINAE（模板代換失敗非錯誤，指在模板例項化過程中的錯誤僅意味此次代換失敗，並不一定產生編譯錯誤）規則及 C11 的 static_assert 等實現相似功能。 include type_traits class B class D public B templatetypename T void SFINAE const stdenable_if_tstdis_base_ofB Tvalue T t templatetypename T void STATIC_ASSERT const T tstatic_assert stdis_podTvalue Use with POD types only 如上所示，stdenable_if（stdenable_if_tboolean Type 是 stdenable_ifboolean Typetype 的縮寫）利用 SFINAE 規則來實現模板型別引數約束的手段之一。其實現方式是若布林判斷為假，則把型別設為 void，而這將導致 const void 這種不合法的型別出現，從而禁止這種型別引數的使用。 static_assert 則在布林判斷失敗時把後面的字串作為訊息內容報告為編譯錯誤。 在編譯時，每個被使用的封閉泛型型別（即是所有泛型引數的實際型別都已被指明的泛型）都會有獨立的編碼產生，編譯程式會在此時確保型別安全性。可是如果泛型要運用其泛型引數的某成員，而該泛型引數又不包含該成員的時候，編譯程式所產生的錯誤資訊或會看似與實際問題無關，增加除錯的難度。 資料來源 參考文獻 延伸閱讀 Gabriel Dos Reis and Jaakko Järvi What is Generic Programming LCSD 2005 Bertrand Meyer Genericity vs Inheritance In OOPSLA First ACM Conference on ObjectOriented Programming Systems Languages and Applications Portland Oregon 29 September2 October 1986 pages 391405 外部連結 genericprogrammingorg Alexander A Stepanov Collected Papers of Alexander A Stepanov creator of the STL CD Walter Bright Templates Revisited David Vandevoorde Nicolai M Josuttis C Templates The Complete Guide 2003 AddisonWesley CNET Jason Clark Introducing Generics in the Microsoft CLR September 2003 MSDN Magazine Microsoft Jason Clark More on Generics in the Microsoft CLR October 2003 MSDN Magazine Microsoft M Aamir Maniar GenericsNet An open source generics library for C DelphiObject Pascal Nick Hodges Delphi 2009 Reviewers Guide October 2008 Embarcadero Developer Network Embarcadero Craig Stuntz Delphi 2009 Generics and Type Constraints October 2008 Dr Bob Delphi 2009 Generics Free Pascal Free Pascal Reference guide Chapter 8 Generics Michaël Van Canneyt 2007 Delphi for Win32 Generics with Delphi 2009 Win32 Sébastien DOERAENE 2008 Delphi for NET Delphi Generics Felix COLIBRI 2008 Eiffel Eiffel ISOECMA specification document Haskell Johan Jeuring Sean Leather José Pedro Magalhães and Alexey Rodriguez Yakushev Libraries for Generic Programming in Haskell Utrecht University Dæv Clarke Johan Jeuring and Andres Löh The Generic Haskell users guide Ralf Hinze Generics for the Masses In Proceedings of the ACM SIGPLAN International Conference on Functional Programming ICFP 2004 Simon Peyton Jones editor The Haskell 98 Language Report Revised 2002 Ralf Lämmel and Simon Peyton Jones Scrap Your Boilerplate A Practical Design Pattern for Generic Programming In Proceedings of the ACM SIGPLAN International Workshop on Types in Language Design and Implementation TLDI03 2003 Also see the website devoted to this research Andres Löh Exploring Generic Haskell PhD thesis 2004 Utrecht University Generic Haskell a language for generic programming Java Gilad Bracha Generics in the Java Programming Language 2004 Maurice Naftalin and Philip Wadler Java Generics and Collections 2006 OReilly Media Inc Peter Sestoft Java Precisely Second Edition 2005 MIT Press 2004 Sun Microsystems Inc Angelika Langer Java Generics FAQs Fanxing Category 多型