第二十二章 泛型
8. Associated Type (关联类型)
当我们在定义协议的时候,定义一个或者多个关联类型作为协议定义的一部分是非常有用的,关联类型会给出一个占位符名称,该占位符名称会作为协议定义的一部分,知道协议被采用的时候,实际为关联类型使用的类型才会被使用。关联类型可以用关键字associatedtype
来加以说明。
8.1 Associated Types in Action (实践中的关联类型)
下面是一个协议Container
,它声明了一个关联类型Item
。
protocol Container {
associatedtype Item
mutating func append(_ item: Item)
var count: Int {
get }
subscript(i: Int) -> Item {
get }
}
该协议Container
定义了三个任何容器都要提供的功能。
- 它必须要用
append(_ : )
方法来给容器里添加新的物品(item)。 - 它必须要能够读取容器中的物品的总数,并且能返回一个
Int
的值 - 它必须要能够用下标语法和
Int
的索引值来检索容器中的每一个物品。
该协议并没有指明容器中的物品时怎样被存储的和什么类型的物品可以存储在容器中。该协议只是指明了三个任何遵循Container
协议的类型必须提供的功能。遵循协议的类型在满足这三个条件的情况下也可以提供其他额外的功能。
任何遵循该Container
协议的类型都必须指明要需要存储值的类型。特别是,它必须确保只有正确类型的物品可以被添加到容器里,并且它还要通过用下标返回来明确物品的类型。
为了定义这三个条件,Container
协议需要在不知道容器中元素的具体类型的情况下引用这种类型, 协议需要指定任何通过 append(_:)
方法添加到容器中的元素和容器中的元素是相同类型,并且通过容器下标返回的元素的类型也是这种类型。
为了实现该目的,协议Container
通过定义一个关联类型Item
可以将该关联类型写成associatedtype Item
,该协议并没有定义什么是Item
,这个信息将留给遵循协议的类型来提供。尽管如此,Item别名还是提供了可以引用容器中元素的方法,并且定义了用来使用append(_:)
方法和下标的一个类型,从而来确保期望Container
来执行的某些行为。
下面是一个非泛型版本IntStack
的类型,采用和遵循来这个Container
协议。
// adopt and conform container protocol
struct IntStack: Container {
// 原IntStack的实现
var items = [Int]() // an array of intger value
mutating func push(_ item: Int) {
items.append(item)
}
mutating func