> 1.0 翻譯:[fd5788](https://github.com/fd5788)?校對:[yankuangshi](https://github.com/yankuangshi),?[stanzhai](https://github.com/stanzhai)
>
> 2.0 翻譯+校對:[wardenNScaiyi](https://github.com/wardenNScaiyi)
本頁包含內容:
[TOC]
本節涉及泛型類型、泛型函數以及泛型初始化器(initializer)的參數,包括形參和實參。聲明泛型類型、函數或初始化器時,須指定相應的類型參數。類型參數相當于一個占位符,當實例化泛型類型、調用泛型函數或泛型初始化器時,就用具體的類型實參替代之。
關于 Swift 語言的泛型概述,見泛型(第二部分第23章)。
## 泛型形參子句
泛型形參子句指定泛型類型或函數的類型形參,以及這些參數的關聯約束和關聯類型要求(requirement)。泛型形參子句用尖括號(<>)包住,并且有以下兩種形式:
>
>
泛型形參列表中泛型形參用逗號分開,其中每一個采用以下形式:
> `類型形參`?:?`約束`
泛型形參由兩部分組成:類型形參及其后的可選約束。類型形參只是占位符類型(如 T,U,V,Key,Value 等)的名字而已。你可以在泛型類型、函數的其余部分或者初始化器聲明,包括函數或初始化器的簽名中使用它(與其任何相關類型)。
約束用于指明該類型形參繼承自某個類或者遵守某個協議或協議的一部分。例如,在下面的泛型函數中,泛型形參`T: Comparable`表示任何用于替代類型形參`T`的類型實參必須滿足`Comparable`協議。
~~~
func simpleMax<T: Comparable>(x: T, _ y: T) -> T {
if x < y {
return y
}
return x
}
~~~
如,`Int`和`Double`均滿足`Comparable`協議,該函數接受任何一種類型。與泛型類型相反,調用泛型函數或初始化器時不需要指定泛型實參子句。類型實參由傳遞給函數或初始化器的實參推斷而出。
~~~
simpleMax(17, 42) // T被推斷出為Int類型
simpleMax(3.14159, 2.71828) // T被推斷出為Double類型
~~~
## Where 子句
要想對類型形參及其關聯類型指定額外關聯類型要求,可以在泛型形參列表之后添加`where`子句。`where`子句由關鍵字`where`及其后的用逗號分割的多個關聯類型要求組成。
`where`子句中的關聯關系用于指明該類型形參繼承自某個類或遵守某個協議或協議的一部分。盡管`where`子句提供了語法糖使其有助于表達類型形參上的簡單約束(如`T: Comparable`等同于`T where T: Comparable`,等等),但是依然可以用來對類型形參及其關聯類型提供更復雜的約束。如,`<T where T: C, T: P>`表示泛型類型`T`繼承自類`C`且遵守協議`P`。
如上所述,可以強制約束類型形參的關聯類型遵守某個協議。例如`<T: Generator where T.Element: Equatable>`表示`T`遵守`Generator`協議,而且`T`的關聯類型`T.Element`遵守`Eauatable`協議(`T`有關聯類型`Element`是因為`Generator`聲明了`Element`,而`T`遵守`Generator`協議)。
也可以用操作符`==`來指定兩個類型等效的關聯關系。例如,有這樣一個約束:`T`和`U`遵守`Generator`協議,同時要求它們的關聯類型等同,可以這樣來表達:`<T: Generator, U: Generator where T.Element == U.Element>`。
當然,替代類型形參的類型實參必須滿足所有類型形參的約束和關聯類型要求。
泛型函數或初始化器可以重載,但在泛型形參子句中的類型形參必須有不同的約束或關聯類型要求,抑或二者皆不同。當調用重載的泛型函數或始化器時,編譯器會用這些約束來決定調用哪個重載函數或始化器。
> 泛型形參子句語法
> 泛型參數子句 → _泛型參數列表_ _約束子句_ 可選 >
> 泛型參數列表 → _泛形參數_ | _泛形參數_ , _泛型參數列表_
> 泛形參數 → _類型名稱_
> 泛形參數 → _類型名稱_ : _類型標識_
> 泛形參數 → _類型名稱_ : _協議合成類型_
> 約束子句 → where _約束列表_
> 約束列表 → _約束_ | _約束_ , _約束列表_
> 約束 → _一致性約束_ | _同類型約束_
> 一致性約束 → _類型標識_ : _類型標識_
> 一致性約束 → _類型標識_ : _協議合成類型_
> 同類型約束 → _類型標識_ == _類型標識_
## 泛型實參子句
泛型實參子句指定_泛型類型_的類型實參。泛型實參子句用尖括號(<>)包住,形式如下:
>
泛型實參列表中類型實參有逗號分開。類型實參是實際具體類型的名字,用來替代泛型類型的泛型形參子句中的相應的類型形參。從而得到泛型類型的一個特化版本。如,Swift標準庫的泛型字典類型定義如下:
~~~
struct Dictionary<KeyTypel: Hashable, ValueType>: Collection, DictionaryLiteralConvertible {
/* .. */
}
~~~
泛型`Dictionary`類型的特化版本,`Dictionary<String, Int>`就是用具體的`String`和`Int`類型替代泛型類型`KeyType: Hashable`和`ValueType`產生的。每一個類型實參必須滿足它所替代的泛型形參的所有約束,包括任何`where`子句所指定的額外的關聯類型要求。上面的例子中,類型形參`Key`類型要求滿足`Hashable`協議,因此`String`也必須滿足`Hashable`協議。
可以用本身就是泛型類型的特化版本的類型實參替代類型形參(假設已滿足合適的約束和關聯類型要求)。例如,為了生成一個元素類型是整型數組的數組,可以用數組的特化版本`Array<Int>`替代泛型類型`Array<T>`的類型形參?`T`?來實現。
~~~
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
~~~
如泛型形參子句所述,不能用泛型實參子句來指定泛型函數或初始化器的類型實參。
> 泛型實參子句語法
> (泛型參數子句Generic Argument Clause) → _泛型參數列表_ >
> 泛型參數列表 → _泛型參數_ | _泛型參數_ , _泛型參數列表_
> 泛型參數 → _類型_
- 介紹
- 歡迎使用 Swift
- 關于 Swift
- Swift 初見
- Swift 版本歷史記錄
- Swift1.0 發布內容
- Swift 教程
- 基礎部分
- 基本運算符
- 字符串和字符
- 集合類型
- 控制流
- 函數
- 閉包
- 枚舉
- 類和結構體
- 屬性
- 方法
- 下標腳本
- 繼承
- 構造過程
- 析構過程
- 自動引用計數
- 可選鏈
- 錯誤處理
- 類型轉換
- 嵌套類型
- 擴展
- 協議
- 泛型
- 權限控制
- 高級操作符
- 語言參考
- 關于語言參考
- 詞法結構
- 類型
- 表達式
- 語句
- 聲明
- 特性
- 模式
- 泛型參數
- 語法總結
- 蘋果官方Blog官方翻譯
- Access Control 權限控制的黑與白
- 造個類型不是夢-白話Swift類型創建
- WWDC里面的那個“大炮打氣球”
- Swift與C語言指針友好合作
- 引用類型和值類型的恩怨
- 訪問控制和Protected
- 可選類型完美解決占位問題