這里的教程為Swift官方教程中文版。

泛型參數(shù)(Generic Parameters and Arguments)


1.0 翻譯:fd5788 校對:yankuangshi, stanzhai

2.0 翻譯+校對:wardenNScaiyi

3.0 翻譯+校對:chenmingjia

本頁包含內(nèi)容:

本節(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 語言的泛型概述,請參閱 泛型。

泛型形參子句

泛型形參子句指定泛型類型或函數(shù)的類型形參,以及這些參數(shù)相關(guān)的約束和要求。泛型形參子句用尖括號(<>)包住,形式如下:

<泛型形參列表>

泛型形參列表中泛型形參用逗號分開,其中每一個(gè)采用以下形式:

類型形參 : 約束

泛型形參由兩部分組成:類型形參及其后的可選約束。類型形參只是占位符類型(如 T,U,V,KeyValue 等)的名字而已。你可以在泛型類型、函數(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)?IntDouble 均滿足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 類型

Where 子句

要想對類型形參及其關(guān)聯(lián)類型指定額外要求,可以在函數(shù)體或者類型的大括號之前添加 where 子句。where 子句由關(guān)鍵字 where 及其后的用逗號分隔的一個(gè)或多個(gè)要求組成。

where : 類型要求

where 子句中的要求用于指明該類型形參繼承自某個(gè)類或符合某個(gè)協(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é)議,這個(gè)約束確保隊(duì)列的每一個(gè)元素都是符合 Equatable 協(xié)議的。

也可以用操作符 == 來指定兩個(gè)類型必須相同。例如,泛型形參子句 <S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element 表示 S1S2 必須都符合 SequenceType 協(xié)議,而且兩個(gè)序列中的元素類型必須相同。

當(dāng)然,替代類型形參的類型實(shí)參必須滿足所有的約束和要求。

泛型函數(shù)或構(gòu)造器可以重載,但在泛型形參子句中的類型形參必須有不同的約束或要求,抑或二者皆不同。當(dāng)調(diào)用重載的泛型函數(shù)或構(gòu)造器時(shí),編譯器會根據(jù)這些約束來決定調(diào)用哪個(gè)重載函數(shù)或構(gòu)造器。

更多關(guān)于泛型where從句的信息和關(guān)于泛型函數(shù)聲明的例子,可以看一看 泛型where子句

泛型形參子句語法

泛型形參子句< 泛型形參列表 約束子句可選 >
</a> 泛型形參列表泛形形參 | 泛形形參 , 泛型形參列表
泛形形參類型名稱
泛形形參類型名稱 : 類型標(biāo)識符
泛形形參類型名稱 : 協(xié)議合成類型

約束子句where 約束列表
</a> 約束列表約束 | 約束 , 約束列表
約束一致性約束 | 同類型約束

一致性約束類型標(biāo)識符 : 類型標(biāo)識符
一致性約束類型標(biāo)識符 : 協(xié)議合成類型
同類型約束類型標(biāo)識符 == 類型

泛型實(shí)參子句

泛型實(shí)參子句指定泛型類型的類型實(shí)參。泛型實(shí)參子句用尖括號(<>)包住,形式如下:

<泛型實(shí)參列表>

泛型實(shí)參列表中類型實(shí)參用逗號分開。類型實(shí)參是實(shí)際具體類型的名字,用來替代泛型類型的泛型形參子句中的相應(yīng)的類型形參。從而得到泛型類型的一個(gè)特化版本。例如,Swift 標(biāo)準(zhǔn)庫中的泛型字典類型的的簡化定義如下:

struct Dictionary<Key: Hashable, Value>: CollectionType, DictionaryLiteralConvertible {
    /* ... */
}

泛型 Dictionary 類型的特化版本,Dictionary<String, Int> 就是用具體的 StringInt 類型替代泛型類型 Key: HashableValue 產(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í)參子句語法
</a> 泛型實(shí)參子句< 泛型實(shí)參列表 >
泛型實(shí)參列表泛型實(shí)參 | 泛型實(shí)參 , 泛型實(shí)參列表
泛型實(shí)參類型

? 模式 語法總結(jié) ?
?