Swift 提供了泛型讓你寫出靈活且可重用的函數和類型。
Swift 标準庫是通過泛型代碼建構出來的。
Swift 的數組和字典類型都是泛型集。
你可以建立一個Int數組,也可建立一個String數組,或者甚至于可以是任何其他 Swift 的類型資料數組。
以下執行個體是一個非泛型函數 exchange 用來交換兩個 Int 值:
以上執行個體隻可以用與交換整數 Int 類型的變量。如果你想要交換兩個 String 值或者 Double 值,就得重新寫個對應的函數,例如 swapTwoStrings(_:_:) 和 swapTwoDoubles(_:_:),如下所示:
從以上代碼來看,它們功能代碼是相同的,隻是類型上不一樣,這時我們可以使用泛型,進而避免重複編寫代碼。
泛型使用了占位類型名(在這裡用字母 T 來表示)來代替實際類型名(例如 Int、String 或 Double)。
swapTwoValues 後面跟着占位類型名(T),并用尖括号括起來(<code><T></code>)。這個尖括号告訴 Swift 那個 T 是 swapTwoValues(_:_:) 函數定義内的一個占位類型名,是以 Swift 不會去查找名為 T 的實際類型。
以下執行個體是一個泛型函數 exchange 用來交換兩個 Int 和 String 值:
Swift 允許你定義你自己的泛型類型。
自定義類、結構體和枚舉作用于任何類型,如同 Array 和 Dictionary 的用法。
接下來我們來編寫一個名為 Stack (棧)的泛型集合類型,棧隻允許在集合的末端添加新的元素(稱之為入棧),且也隻能從末端移除元素(稱之為出棧)。

圖檔中從左到右解析如下:
三個值在棧中。
第四個值被壓入到棧的頂部。
現在有四個值在棧中,最近入棧的那個值在頂部。
棧中最頂部的那個值被移除,或稱之為出棧。
移除掉一個值後,現在棧又隻有三個值了。
以下執行個體是一個非泛型版本的棧,以 Int 型的棧為例:
這個結構體在棧中使用一個名為 items 的 Array 屬性來存儲值。Stack 提供了兩個方法:push(_:) 和 pop(),用來向棧中壓入值以及從棧中移除值。這些方法被标記為 mutating,因為它們需要修改結構體的 items 數組。
上面的 IntStack 結構體隻能用于 Int 類型。不過,可以定義一個泛型 Stack 結構體,進而能夠處理任意類型的值。
下面是相同代碼的泛型版本:
Stack 基本上和 IntStack 相同,占位類型參數 Element 代替了實際的 Int 類型。
以上執行個體中 Element 在如下三個地方被用作占位符:
建立 items 屬性,使用 Element 類型的空數組對其進行初始化。
指定 push(_:) 方法的唯一參數 item 的類型必須是 Element 類型。
指定 pop() 方法的傳回值類型必須是 Element 類型。
當你擴充一個泛型類型的時候(使用 extension 關鍵字),你并不需要在擴充的定義中提供類型參數清單。更加友善的是,原始類型定義中聲明的類型參數清單在擴充裡是可以使用的,并且這些來自原始類型中的參數名稱會被用作原始定義中類型參數的引用。
下面的例子擴充了泛型類型 Stack,為其添加了一個名為 topItem 的隻讀計算型屬性,它将會傳回目前棧頂端的元素而不會将其從棧中移除:
執行個體中 topItem 屬性會傳回一個 Element 類型的可選值。當棧為空的時候,topItem 會傳回 nil;當棧不為空的時候,topItem 會傳回 items 數組中的最後一個元素。
以上程式執行輸出結果為:
我們也可以通過擴充一個存在的類型來指定關聯類型。
例如 Swift 的 Array 類型已經提供 append(_:) 方法,一個 count 屬性,以及一個接受 Int 類型索引值的下标用以檢索其元素。這三個功能都符合 Container 協定的要求,是以你隻需簡單地聲明 Array 采納該協定就可以擴充 Array。
以下執行個體建立一個空擴充即可:
類型限制指定了一個必須繼承自指定類的類型參數,或者遵循一個特定的協定或協定構成。
你可以寫一個在一個類型參數名後面的類型限制,通過冒号分割,來作為類型參數鍊的一部分。這種作用于泛型函數的類型限制的基礎文法如下所示(和泛型類型的文法相同):
上面這個函數有兩個類型參數。第一個類型參數 T,有一個要求 T 必須是 SomeClass 子類的類型限制;第二個類型參數 U,有一個要求 U 必須符合 SomeProtocol 協定的類型限制。
Swift 中使用 associatedtype 關鍵字來設定關聯類型執行個體。
下面例子定義了一個 Container 協定,該協定定義了一個關聯類型 ItemType。
Container 協定隻指定了三個任何遵從 Container 協定的類型必須提供的功能。遵從協定的類型在滿足這三個條件的情況下也可以提供其他額外的功能。
類型限制能夠確定類型符合泛型函數或類的定義限制。
你可以在參數清單中通過where語句定義參數的限制。
你可以寫一個where語句,緊跟在在類型參數清單後面,where語句後跟一個或者多個針對關聯類型的限制,以及(或)一個或多個類型和關聯類型間的等價(equality)關系。
下面的例子定義了一個名為allItemsMatch的泛型函數,用來檢查兩個Container執行個體是否包含相同順序的相同元素。
如果所有的元素能夠比對,那麼傳回 true,反之則傳回 false。