1.0 翻譯:fd5788 校對:yankuangshi, stanzhai
2.0 翻譯+校對:wardenNScaiyi
3.0 翻譯+校對:chenmingjia
4.1 翻譯+校對:mylittleswift
本頁包含內(nèi)容:
本節(jié)涉及泛型類型、泛型函數(shù)以及泛型構(gòu)造器的參數(shù),包括形參和實(shí)參。聲明泛型類型、函數(shù)或構(gòu)造器時(shí),須指定相應(yīng)的類型參數(shù)。類型參數(shù)相當(dāng)于一個占位符,當(dāng)實(shí)例化泛型類型、調(diào)用泛型函數(shù)或泛型構(gòu)造器時(shí),就用具體的類型實(shí)參替代之。
關(guān)于 Swift 語言的泛型概述,請參閱 泛型。
泛型形參子句指定泛型類型或函數(shù)的類型形參,以及這些參數(shù)相關(guān)的約束和要求。泛型形參子句用尖括號(<>)包住,形式如下:
<
泛型形參列表>
泛型形參列表中泛型形參用逗號分開,其中每一個采用以下形式:
類型形參:約束
泛型形參由兩部分組成:類型形參及其后的可選約束。類型形參只是占位符類型(如 T,U,V,Key,Value 等)的名字而已。你可以在泛型類型、函數(shù)的其余部分或者構(gòu)造器聲明,包括函數(shù)或構(gòu)造器的簽名中使用它(以及它的關(guān)聯(lián)類型)。
約束用于指明該類型形參繼承自某個類或者符合某個協(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 類型
要想對類型形參及其關(guān)聯(lián)類型指定額外要求,可以在函數(shù)體或者類型的大括號之前添加 where 子句。where 子句由關(guān)鍵字 where 及其后的用逗號分隔的一個或多個要求組成。
where:類型要求
where 子句中的要求用于指明該類型形參繼承自某個類或符合某個協(xié)議或協(xié)議組合。盡管 where 子句提供了語法糖使其有助于表達(dá)類型形參上的簡單約束(如 <T: Comparable> 等同于 <T> where T: Comparable,等等),但是依然可以用來對類型形參及其關(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é)議,這個約束確保隊(duì)列的每一個元素都是符合 Equatable 協(xié)議的。
也可以用操作符 == 來指定兩個類型必須相同。例如,泛型形參子句 <S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element 表示 S1 和 S2 必須都符合 SequenceType 協(xié)議,而且兩個序列中的元素類型必須相同。
當(dāng)然,替代類型形參的類型實(shí)參必須滿足所有的約束和要求。
泛型函數(shù)或構(gòu)造器可以重載,但在泛型形參子句中的類型形參必須有不同的約束或要求,抑或二者皆不同。當(dāng)調(diào)用重載的泛型函數(shù)或構(gòu)造器時(shí),編譯器會根據(jù)這些約束來決定調(diào)用哪個重載函數(shù)或構(gòu)造器。
更多關(guān)于泛型 where 從句的信息和關(guān)于泛型函數(shù)聲明的例子,可以看一看 泛型 where 子句
泛型形參子句語法
泛型形參子句 → < 泛型形參列表 約束子句可選 > 泛型形參列表 → 泛形形參 | 泛形形參 , 泛型形參列表 泛形形參 → 類型名稱 泛形形參 → 類型名稱 : 類型標(biāo)識符 泛形形參 → 類型名稱 : 協(xié)議合成類型
一致性約束 → 類型標(biāo)識符 : 類型標(biāo)識符 一致性約束 → 類型標(biāo)識符 : 協(xié)議合成類型 同類型約束 → 類型標(biāo)識符 == 類型
泛型實(shí)參子句指定泛型類型的類型實(shí)參。泛型實(shí)參子句用尖括號(<>)包住,形式如下:
<
泛型實(shí)參列表>
泛型實(shí)參列表中類型實(shí)參用逗號分開。類型實(shí)參是實(shí)際具體類型的名字,用來替代泛型類型的泛型形參子句中的相應(yīng)的類型形參。從而得到泛型類型的一個特化版本。例如,Swift 標(biāo)準(zhǔn)庫中的泛型字典類型的的簡化定義如下:
struct Dictionary<Key: Hashable, Value>: CollectionType, DictionaryLiteralConvertible {
/* ... */
}
泛型 Dictionary 類型的特化版本,Dictionary<String, Int> 就是用具體的 String 和 Int 類型替代泛型類型 Key: Hashable 和 Value 產(chǎn)生的。每一個類型實(shí)參必須滿足它所替代的泛型形參的所有約束,包括任何 where 子句所指定的額外的關(guān)聯(lián)類型要求。上面的例子中,類型形參 Key 的類型必須符合 Hashable 協(xié)議,因此 String 也必須滿足 Hashable 協(xié)議。
可以用本身就是泛型類型的特化版本的類型實(shí)參替代類型形參(假設(shè)已滿足合適的約束和關(guān)聯(lián)類型要求)。例如,為了生成一個元素類型是整型數(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í)參 → 類型