iOS Swift No.22 - 泛型5

第二十二章 泛型

11. Contextual Where Clauses (前后关系的where子句)

我们可以写一个没用类型约束的泛型where子句作为声明的一部分。当前我们正应用于where子句的上下文中。举个例子,在泛型类型的下标里写泛型where子句或在泛型类型的扩展里写一个方法。Container结构体是一个泛型,下面的例子中指明了where子句满足哪些约束才可以在新的方法上使用。

extension Container {
    func average() -> Double where Item == Int {
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }
    func endsWith(_ item: Item) -> Bool where Item: Equatable {
        return count >= 1 && self[count-1] == item
    }
}
let numbers = [1260, 1200, 98, 37]
print(numbers.average()) // Prints "648.75"
print(numbers.endsWith(37)) // Prints "true"

上例给Container里面添加了一个average()方法,当Container里的物品都是整数的时候,添加 endsWith(_:)方法当物品都是相同的情况下,这两个函数都包括一个泛型where子句,该子句将类型约束添加到来自容器原始声明的泛型Item类型参数中。

如果我们没有用前后关系的where子句,那么我们要为每一个泛型where子句各写一个扩展,上面的例子和下面的例子作用是一样的。

extension Container where Item == Int {
    func average() -> Double {
        var sum = 0.0
        for index in 0..<count {
            sum += Double(self[index])
        }
        return sum / Double(count)
    }
}
extension Container where Item: Equatable {
    func endsWith(_ item: Item) -> Bool {
        return count >= 1 && self[count-1] == item
    }
}

在这个版本的例子中使用前后关系的where子句,在相同的扩展中实现了verage()endsWith(_:) 方法,因为没一个方法的泛型where子句指出需要满足的要求,才能使该方法可用。将这些要求移动到扩展的泛型,其中子句使方法在相同情况下可用,但每个要求需要一个扩展。

12. Associated Types with a Generic Where Clause (泛型where子句的关联类型)

我们可以包括在关联类型里面包含泛型where子句,举个例子,假设我们想要写一个包含爹地的Container版本,就像swift标准库里Sequence协议那样,下面是如何用代码实现

protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }

    associatedtype Iterator: IteratorProtocol where Iterator.Element == Item
    func makeIterator() -> Iterator
}

Iterator里的泛型where子句请求迭代必须经过相同物品类型的元素作为容器中的物品。不管迭代的类型,该makeIterator()方法提供了容器迭代的读取权。

而继承自另一个协议的协议,通过在协议的声明里包括泛型where子句给继承的关联类型添加约束,举个例子,下面的代码声明了请求Item遵循Comparable的协议ComparableContainer

// ComparableContainer继承Container 泛型where子句请求Item遵循Comparable
protocol ComparableContainer: Container where Item: Comparable { }

13. Generic Subscripts (泛型下标)

下标也可以是泛型,并且还可以包含泛型where子句,所以我们可以在关键字subscript后面尖括号内写占位符类型名,并且在下标体的大括号前写泛型where子句。例如:

extension Container {
	// 如何写一个泛型下标
    subscript<Indices: Sequence>(indices: Indices) -> [Item]
        where Indices.Iterator.Element == Int {
            var result = [Item]()
            for index in indices {
                result.append(self[index])
            }
            return result
    }
}

给Container协议的下标添加一个采用索引顺序的下标,并且返回一个包含给出索引值的物品的数组, 如下是泛型下标的限制条件:

  • 尖括号内的泛型参数Indices必须是遵循来自swift标准库里的Sequence协议一个类型
  • 该下标采用的是一个单一的参数indices,是一个Indices类型的实例
  • 泛型where子句要求给顺序的循环必须经过类型Int的所有元素。这样确保了顺序中索引和用于容器中的索引是同一个类型。

所以这三个限制条件组合在一起,意味着传入给indices的参数是一个整数顺序。

猜你喜欢

转载自blog.csdn.net/weixin_45026183/article/details/107308071