翻譯:fd5788
校對:yankuangshi, stanzhai

泛型參數


本頁包含內容:

本節涉及泛型類型、泛型函數以及泛型構造器的參數,包括形參和實參。聲明泛型類型、函數或構造器時,須指定相應的類型參數。類型參數相當於一個佔位符,當實例化泛型類型、調用泛型函數或泛型構造器時,就用具體的類型實參替代之。

關於 Swift 語言的泛型概述,見泛型(第二部分第22章)。

泛型形參子句

泛型形參子句指定泛型類型或函數的類型形參,以及這些參數的關聯約束和要求。泛型形參子句用尖括號(<>)包住,並且有以下兩種形式:

<generic parameter list>
<generic parameter list where requirements>

泛型形參列表中泛型形參用逗號分開,每一個採用以下形式:

type parameter : constrain

泛型形參由兩部分組成:類型形參及其後的可選約束。類型形參只是佔位符類型(如T,U,V,KeyType,ValueType等)的名字而已。你可以在泛型類型、函數的其餘部分或者構造器聲明,以及函數或構造器的簽名中使用它。

約束用於指明該類型形參繼承自某個類或者遵守某個協議或協議的一部分。例如,在下面的泛型中,泛型形參T: Comparable表示任何用於替代類型形參T的類型實參必須滿足Comparable協議。

  1. func simpleMin<T: COmparable>(x: T, y: T) -> T {
  2. if x < y {
  3. return y
  4. }
  5. return x
  6. }

如,IntDouble均滿足Comparable協議,該函數接受任何一種類型。與泛型類型相反,調用泛型函數或構造器時不需要指定泛型實參子句。類型實參由傳遞給函數或構造器的實參推斷而出。

  1. simpleMin(17, 42) // T is inferred to be Int
  2. simpleMin(3.14159, 2.71828) // T is inferred to be 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有關聯類型是因為Generator聲明了Element,而T遵守Generator協議)。

也可以用操作符==來指定兩個類型等效的要求。例如,有這樣一個約束:TU遵守Generator協議,同時要求它們的關聯類型等同,可以這樣來表達:<T: Generator, U: Generator where T.Element == U.Element>

當然,替代類型形參的類型實參必須滿足所有類型形參所要求的約束和要求。

泛型函數或構造器可以重載,但在泛型形參子句中的類型形參必須有不同的約束或要求,抑或二者皆不同。當調用重載的泛型函數或構造器時,編譯器會用這些約束來決定調用哪個重載函數或構造器。

泛型類可以生成一個子類,但是這個子類也必須是泛型類。

泛型形參子句語法
泛型參數子句< 泛型參數列表 約束子句 可選 >
泛型參數列表泛形參數 | 泛形參數 , 泛型參數列表
泛形參數類型名稱
泛形參數類型名稱 : 類型標識
泛形參數類型名稱 : 協議合成類型
約束子句where 約束列表
約束列表約束 | 約束 , 約束列表
約束一致性約束 | 同類型約束
一致性約束類型標識 : 類型標識
一致性約束類型標識 : 協議合成類型
同類型約束類型標識 == 類型標識

泛型實參子句

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

<generic argument list>

泛型實參列表中類型實參有逗號分開。類型實參是實際具體類型的名字,用來替代泛型類型的泛型形參子句中的相應的類型形參。從而得到泛型類型的一個特化版本。如,Swift標準庫的泛型字典類型定義如下:

  1. struct Dictionary<KeyTypel: Hashable, ValueType>: Collection, DictionaryLiteralConvertible {
  2. /* .. */
  3. }

泛型Dictionary類型的特化版本,Dictionary<String, Int>就是用具體的StringInt類型替代泛型類型KeyType: HashableValueType產生的。每一個類型實參必須滿足它所替代的泛型形參的所有約束,包括任何where子句所指定的額外的要求。上面的例子中,類型形參KeyType要求滿足Hashable協議,因此String也必須滿足Hashable協議。

可以用本身就是泛型類型的特化版本的類型實參替代類型形參(假設已滿足合適的約束和要求)。例如,為了生成一個元素類型是整型數組的數組,可以用數組的特化版本Array<Int>替代泛型類型Array<T>的類型形參T來實現。

  1. let arrayOfArrays: Array<Array<Int>> = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

泛型形參子句所述,不能用泛型實參子句來指定泛型函數或構造器的類型實參。

泛型實參子句語法
(泛型參數子句Generic Argument Clause)< 泛型參數列表 >
泛型參數列表泛型參數 | 泛型參數 , 泛型參數列表
泛型參數類型