Swift 5.x 关联类型
2020-07-10 本文已影响0人
ShenYj
- 定义一个协议时, 有时在协议定义里声明一个或多个关联类型是很有用的. 关联类型给协议中用到的类型一个占位符名称. 直到采纳协议时, 才指定用于该关联类型的实际类型. 关联类型通过
associatedtype
关键字指定.
关联类型的应用
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
- 这个协议没有指定元素如何储存在容器中, 也没有指定允许存入容器的元素类型. 协议仅仅指定了想成为一个
Container
的类型, 必须提供的三种功能. 遵循该协议的类型可以提供其他功能, 只要满足这三个要求即可. - 任何遵循
Container
协议的类型必须能指定其存储值的类型. 尤其是它必须保证只有正确类型的元素才能添加到容器中, 而且该类型下标返回的元素类型必须是正确的. - 为了定义这些要求.
Container
协议需要一种在不知道容器具体类型的情况下, 引用该容器将存储的元素类型的方法.Container
协议需要制定所有传给append(_:)
方法的值必须和容器里元素的值类型一样的. 而且容器下标返回值也是和容器里元素的值类型相同.
个人理解: 感觉就是Swift在Protocol下定义泛型的一种语法标准, 如果按照struct的方式去定义protocol泛型, <T>这种写法会直接警报的
struct IntStack: Container {
// original IntStack implementation
var items = [Int]()
mutating func push(_ item: Int) {
items.append(item)
}
mutating func pop() -> Int {
items.removeLast()
}
// conformance to the Container protocol
typealias ItemType = Int
mutating func append(_ item: Int) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Int {
return items[i]
}
}
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
泛型版本:
struct Stack<Element>: Container {
// original IntStack implementation
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
items.removeLast()
}
// conformance to the Container protocol
// Swift会自动推导出类型
// typealias ItemType = Element
mutating func append(_ item: Element) {
self.push(item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> Element {
return items[i]
}
}
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
关联类型的约束
- 你可以在协议里给关联类型添加约束来要求遵循的类型满足约束.
protocol Container {
// 要求其元素遵循Equatable协议
associatedtype ItemType: Equatable
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
- 协议也可以作为它自身的要求出现.
protocol SuffixableContainer {
associatedtype SuffixableContainer: SuffixableContainer where Suffix.Item == Item
func suffix(_ size: Int) -> Suffix
}