-
如类型约束中描述的一样, 类型约束允许你在泛型函数或泛型类型相关的类型形式参数上定义要求.
-
类型约束在为关联类型定义要求时也很有用.通过定义一个泛型
Where
子句来实现. 泛型Where
子句让你能够要求一个关联类型必须遵循指定的协议, 或者指定的类型形式参数和关联类型必须相同. 泛型Where
子句以Where
关键字开头, 后面关联类型的约束或类型和关联类型一致的关系. 泛型Where
子句写在一个类型或函数体的左半个大括号前面.
e.g.
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.ItemType == C2.ItemType, C1.ItemType: Equatable {
// check that both containers contain the same number of items.
if someContainer.count != anotherContainer.count {
return false
}
// check each pair of items to see if they're equivalent.
for i in 0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
return false
}
}
return true
}
泛型类型限制部分
- C1必须遵循Container协议(写作
C1: Container
) - C2也必须遵循Container协议(写作
C2: Container
) - C1的ItemType必须和C2的ItemType相同(写作
C1.ItemType == C2.ItemType
) - C1的ItemType必须遵循Equatable协议(写作
C1.ItemType: Equatable
)
where子句部分
- someContainer是一个
C1
类型的容器 - anotherContainer是一个
C2
类型的容器 - someContainer和anotherContainer中的元素类型相同
- someContainer中的元素可以通过不等操作符(
!=
)检查它们是否不一样
带有泛型Where
子句的扩展
- 可以使用泛型的
where
子句来作为扩展的一部分.
e.g.
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
items.removeLast()
}
}
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}
e.g.
protocol Container {
associatedtype ItemType
mutating func append(_ item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
extension Container where ItemType == Double {
func average() -> Double {
var sum = 0.0
for index in 0..<count {
sum += self[index]
}
return sum / Double(count)
}
}
网友评论