泛型参数

本文介绍了泛型类型,泛型函数和泛型构造器的参数,包含形参和实参。 声明泛型类型、泛型函数、泛型下标或泛型构造器时,需要指定相应的类型参数。 这些类型参数会充当占位符,并在创建泛型类型实例、调用泛型函数或泛型构造器时,被替换成实际的具体类型参数。

有关 Swift 中泛型的概述, 查看 泛型


泛型形参子句

泛型形参子句 指定了泛型类型或函数的类型形参,以及对这些参数的相关约束和要求。 泛型形参子句包含在尖括号( <> )中,并具有以下形式:

<generic parameter list>

泛型形参列表 是以逗号分隔的泛型形参列表,每个形参都具有以下形式:

type parameter: constraint

泛型形参由 类型形参 和可选的 约束 组成。 类型形参 只是占位符类型的名称(例如,TUVKeyValue 等)。 你可以在泛型类型、函数或初始化方法的其余部分,包括函数或初始化方法的签名中,访问类型形参(及其任何关联类型)。

constraint 表明类型形参是继承自特定类,或是符合某个协议或协议组合。 例如,在下面的泛型函数中,泛型形参 T: Comparable 表示用于替换类型形参 T 的任何类型实参必须符合 Comparable 协议。

func simpleMax<T: Comparable>(_ x: T, _ y: T) -> T {
    if x < y {
        return y
    }
    return x
}

因为 IntDouble 都符合 Comparable 协议,所以这个函数可以接受这两种泛型实参。 和泛型类型不同,在调用泛型函数或初始化方法时,不用指定泛型实参子句。 相反,类型实参是从传递给函数或初始化方法的参数类型推断出来的。

simpleMax(17, 42) // T 被推断为 Int
simpleMax(3.14159, 2.71828) // T 被推断为 Double

泛型 Where 子句

你可以通过在类型或函数体的起始大括号之前加入泛型 where 子句,来对类型行参及其关联类型做一些额外要求。 泛型 where 子句由 where 关键字组成,后面跟着用逗号分隔的一个或多个 要求 列表。

where requirements

泛型 where 子句中的 requirements 可以指定类型行参继承自某一个具体的类,或者要求符合某一个协议或协议组合。虽然泛型 where 子句提供了语法糖,用于表达类型行参的简单约束(例如,<T:Comparable> 相当于 <T> where T: Comparable 等),但你还是可以使用它来为类型行参及其相关类型提供更加复杂的约束。举个例子,你可以约束类型行参的关联类型以符合某个协议。例如,<S: Sequence> where S.Iterator.Element: Equatable 指定 S 符合 Sequence 协议,并且关联类型 S.Iterator.Element 符合 Equatable 协议。该约束确保了序列的每个元素是可相等的。

你还可以使用 == 运算符来指定两个类型相等的关联关系。例如,<S1: Sequence, S2: Sequence> where S1.Iterator.Element == S2.Iterator.Element 描述了 S1S2 符合 Sequence 协议的约束条件,并且这两个元素必须是相同的类型。

用于替换类型形参的任何类型实参必须满足对类型形参的所有约束和要求。

泛型函数或初始化方法支持重载,但需要保证类型形参必须有不同的约束或关联类型要求,抑或是二者皆不同。 当你调用重载的泛型函数或初始化方法时,编译器会根据这些约束来决定要调用的重载函数或初始化方法。

有关泛型 where 子句的更多信息,以及有关在泛型函数声明中的示例,查看 泛型 Where 子句

泛型形参子句的语法

泛型参数子句  → < 通用参数列表 >

泛型参数列表  → 泛型参数 | 泛型参数 , 泛型参数列表

泛型参数 → 类型名称

泛型参数 → 类型名称 : 类型标识

泛型参数 → 类型名称 : 组合协议类型

泛型 where 子句  → where 约束列表

约束列表  → 约束 | 约束 , 约束列表

约束  → 一致性约束 | 同类型约束

一致性约束  → 类型标识 : 类型标识

一致性约束  → 类型标识 : 组合协议类型

同类型约束  → 类型标识 == 类型


泛型实参子句

泛型实参子句 表示泛型类型的实参。泛型实参子句包含在尖括号(<>)中,并具有以下形式:

<generic argument list>

泛型实参子句 是由逗号分隔的类型实参列表。类型实参 是实际具体类型的名称,用来替换泛型类型的泛型形参子句中的相应类型形参。它得到是一个该泛型类型的特定版本。 下面的示例展示了 Swift 标准库中的泛型字典类型的简化版本。

struct Dictionary<Key: Hashable, Value>: Collection, ExpressibleByDictionaryLiteral {
    /* ... */
}

泛型 Dictionary 类型的特定版本,Dictionary<String, Int> 是通过使用具体的类型参数 StringInt 替换泛型参数 Key:HashableValue 而构成的。 每个类型实参必须满足它所替换的泛型形参的所有约束,包括泛型 where 子句中指定的额外要求。 在上面的例子中,Key 类型参数被约束为遵守 Hashable 协议,因此 String 也必须遵守 Hashable 协议。

你可以使用本身就是泛型类型的特定版本的类型实参来替换类型形参(前提是已满足合适的约束和关联类型要求)。 例如,你可以使用特定版本的数组 Array <Int> 替换 Array <Element> 中的类型参数 Element ,以构成一个数组,其元素本身就是整数数组。

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

泛型形参子句 中所述,你不能使用泛型形参子句来指定泛型函数的类型参数或初始化方法。

泛型实参子句语法

泛型实参子句  → < 泛型实参列表  >

泛型实参列表  → 泛型实参 | 泛型实参 , 泛型实参列表

泛型实参 → 类型

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~