下标支持泛型
由于需要转换字典的每一个值,在swift3中使用混合数据类型的字典是相当痛苦的工作,而在swift4允许下标操作返回一个泛型类型。
1 | struct Grade { |
swift4中下标支持泛型。例如,可以实现一种使用下标从集合中检索并返回值数组的方法。
1 | extension Grade { subscript<Keys: Sequence>(keys: Keys) -> [Any] where Keys.Element == String { var values: [Any] = [] for key in keys { if let value = data[key] { values.append(value) } } return values } } gradebook[["name", "grade"]] gradebook[Set(["name", "grade"])] // 均返回 ["Neil Armstrong", 97] |
可以使用这个特性向标准库类型中添加新功能。
1 | extension Collection { subscript<Indices: Sequence>(indices: Indices) -> [Element] where Indices.Element == Index { var result: [Element] = [] for index in indices { result.append(self[index]) } return result } } let words = "It was the best of times it was the worst of times" .split(separator: " ") words[[3, 9, 11]] // ["best", "worst", "times"] |
Associated Type 可以追加 Where 约束语句
前面的两个示例都利用了另一个新特性:关联类型约束。关联类型现在可以用where子句约束,这可以大大简化泛型.
在Swift4中可以在associatedtype后面声明的类型后追加where语句
1 | associatedtype Element where <xxx> |
看下面是 Swift 4 标准库中 Sequence 中 Element 的声明:
1 | protocol Sequence { |
它限定了Sequence中Element这个类型必须和Iterator.Element的类型一致。
通过 where 语句可以对类型添加更多的约束,使其更严谨,避免在使用这个类型时做多余的类型判断。
例如在Grade的拓展中,swift3要求必须明确where Keys.Iterator.Element == String.关联类型约束可以更容易的拓展标准库类型。
extension Sequence where Element: Numeric {
var product: Element {
return self.reduce(1, *)
}
}
[2,4,6,8].product
// 384
[1.5, 3.0, -2.0].product
// -9 (a Double)