为泛型定义要求

优质
小牛编辑
129浏览
2023-12-01

为泛型定义要求

  • 如类型约束中描述的一样, 类型约束允许你在泛型函数或泛型类型相关的类型形式参数上定义要求.

  • 类型约束在为关联类型定义要求时也很有用.通过定义一个泛型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)
    }
}