本節(jié)涉及泛型類型、泛型函數(shù)以及泛型構(gòu)造器的參數(shù),包括形參和實(shí)參。聲明泛型類型、函數(shù)或構(gòu)造器時(shí),須指定相應(yīng)的類型參數(shù)。類型參數(shù)相當(dāng)于一個(gè)占位符,當(dāng)實(shí)例化泛型類型、調(diào)用泛型函數(shù)或泛型構(gòu)造器時(shí),就用具體的類型實(shí)參替代之。
關(guān)于 Swift 語言的泛型概述,請(qǐng)參閱 泛型。
泛型形參子句指定泛型類型或函數(shù)的類型形參,以及這些參數(shù)相關(guān)的約束和要求。泛型形參子句用尖括號(hào)(<>
)包住,形式如下:
<
泛型形參列表
>
泛型形參列表中泛型形參用逗號(hào)分開,其中每一個(gè)采用以下形式:
類型形參
:約束
泛型形參由兩部分組成:類型形參及其后的可選約束。類型形參只是占位符類型(如 T
,U
,V
,Key
,Value
等)的名字而已。你可以在泛型類型、函數(shù)的其余部分或者構(gòu)造器聲明,包括函數(shù)或構(gòu)造器的簽名中使用它(以及它的關(guān)聯(lián)類型)。
約束用于指明該類型形參繼承自某個(gè)類或者符合某個(gè)協(xié)議或協(xié)議組合。例如,在下面的泛型函數(shù)中,泛型形參 T: Comparable
表示任何用于替代類型形參 T
的類型實(shí)參必須滿足 Comparable
協(xié)議。
func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
if x < y {
return y
}
return x
}
例如,因?yàn)?Int
和 Double
均滿足 Comparable
協(xié)議,所以該函數(shù)可以接受這兩種類型。與泛型類型相反,調(diào)用泛型函數(shù)或構(gòu)造器時(shí)不需要指定泛型實(shí)參子句。類型實(shí)參由傳遞給函數(shù)或構(gòu)造器的實(shí)參推斷而出。
simpleMax(17, 42) // T 被推斷為 Int 類型
simpleMax(3.14159, 2.71828) // T 被推斷為 Double 類型
要想對(duì)類型形參及其關(guān)聯(lián)類型指定額外要求,可以在函數(shù)體或者類型的大括號(hào)之前添加 where
子句。where
子句由關(guān)鍵字 where
及其后的用逗號(hào)分隔的一個(gè)或多個(gè)要求組成。
where
:類型要求
where
子句中的要求用于指明該類型形參繼承自某個(gè)類或符合某個(gè)協(xié)議或協(xié)議組合。盡管 where
子句提供了語法糖使其有助于表達(dá)類型形參上的簡單約束(如 <T: Comparable>
等同于 <T> where T: Comparable
,等等),但是依然可以用來對(duì)類型形參及其關(guān)聯(lián)類型提供更復(fù)雜的約束,例如你可以強(qiáng)制形參的關(guān)聯(lián)類型遵守協(xié)議,如,<S: Sequence> where S.Iterator.Element: Equatable
表示泛型類型 S
遵守 Sequence
協(xié)議并且關(guān)聯(lián)類型 S.Iterator.Element
遵守 Equatable
協(xié)議,這個(gè)約束確保隊(duì)列的每一個(gè)元素都是符合 Equatable
協(xié)議的。
也可以用操作符 ==
來指定兩個(gè)類型必須相同。例如,泛型形參子句 <S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element
表示 S1
和 S2
必須都符合 SequenceType
協(xié)議,而且兩個(gè)序列中的元素類型必須相同。
當(dāng)然,替代類型形參的類型實(shí)參必須滿足所有的約束和要求。
泛型函數(shù)或構(gòu)造器可以重載,但在泛型形參子句中的類型形參必須有不同的約束或要求,抑或二者皆不同。當(dāng)調(diào)用重載的泛型函數(shù)或構(gòu)造器時(shí),編譯器會(huì)根據(jù)這些約束來決定調(diào)用哪個(gè)重載函數(shù)或構(gòu)造器。
更多關(guān)于泛型 where 從句的信息和關(guān)于泛型函數(shù)聲明的例子,可以看一看 泛型 where 子句。
泛型形參子句語法
泛形形參 → 類型名稱
泛形形參 → 類型名稱 : 類型標(biāo)識(shí)符
泛形形參 → 類型名稱 : 協(xié)議合成類型
requirement-clause
約束子句 → where 約束列表
conformance-requirement
一致性約束 → 類型標(biāo)識(shí)符 : 類型標(biāo)識(shí)符
一致性約束 → 類型標(biāo)識(shí)符 : 協(xié)議合成類型
同類型約束 → 類型標(biāo)識(shí)符 == 類型
泛型實(shí)參子句指定泛型類型的類型實(shí)參。泛型實(shí)參子句用尖括號(hào)(<>
)包住,形式如下:
<
泛型實(shí)參列表
>
泛型實(shí)參列表中類型實(shí)參用逗號(hào)分開。類型實(shí)參是實(shí)際具體類型的名字,用來替代泛型類型的泛型形參子句中的相應(yīng)的類型形參。從而得到泛型類型的一個(gè)特化版本。例如,Swift 標(biāo)準(zhǔn)庫中的泛型字典類型的的簡化定義如下:
struct Dictionary<Key: Hashable, Value>: CollectionType, DictionaryLiteralConvertible {
/* ... */
}
泛型 Dictionary
類型的特化版本,Dictionary<String, Int>
就是用具體的 String
和 Int
類型替代泛型類型 Key: Hashable
和 Value
產(chǎn)生的。每一個(gè)類型實(shí)參必須滿足它所替代的泛型形參的所有約束,包括任何 where
子句所指定的額外的關(guān)聯(lián)類型要求。上面的例子中,類型形參 Key
的類型必須符合 Hashable
協(xié)議,因此 String
也必須滿足 Hashable
協(xié)議。
可以用本身就是泛型類型的特化版本的類型實(shí)參替代類型形參(假設(shè)已滿足合適的約束和關(guān)聯(lián)類型要求)。例如,為了生成一個(gè)元素類型是整型數(shù)組的數(shù)組,可以用數(shù)組的特化版本 Array<Int>
替代泛型類型 Array<T>
的類型形參 T
來實(shí)現(xiàn)。
let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
如 泛型形參子句 所述,不能用泛型實(shí)參子句來指定泛型函數(shù)或構(gòu)造器的類型實(shí)參。
泛型實(shí)參子句語法
泛型實(shí)參子句 → < 泛型實(shí)參列表 >
泛型實(shí)參列表 → 泛型實(shí)參 | 泛型實(shí)參 , 泛型實(shí)參列表
泛型實(shí)參 → 類型