【发布时间】:2015-10-25 17:19:47
【问题描述】:
我想扩展 Array 以增加对新协议的一致性 - 但仅限于其元素本身符合特定协议的数组。
更一般地说,我希望具有类型参数的类型(无论是协议还是具体类型)仅在类型参数匹配某些约束时才实现协议。
从 Swift 2.0 开始,这似乎是不可能的。有没有我想念的方法?
示例
假设我们有Friendly 协议:
protocol Friendly {
func sayHi()
}
我们可以扩展现有类型来实现它:
extension String: Friendly {
func sayHi() {
print("Greetings from \(self)!")
}
}
"Sally".sayHi()
当sayHi()的元素都是Friendly时,我们也可以扩展Array来实现sayHi():
extension Array where Element: Friendly {
func sayHi() {
for elem in self {
elem.sayHi()
}
}
}
["Sally", "Fred"].sayHi()
此时,[Friendly] 类型本身应该实现 Friendly,因为它符合协议的要求。 但是,这段代码无法编译:
extension Array: Friendly where Element: Friendly {
func sayHi() {
for elem in self {
elem.sayHi()
}
}
}
错误消息是“带有约束的 'Array' 类型的扩展不能有继承子句”,这似乎彻底关闭了直接方法的大门。
有间接的解决方法吗?我可以使用一些聪明的技巧吗?也许有一种方法涉及扩展SequenceType 而不是Array?
一个可行的解决方案可以编译这段代码:
let friendly: Friendly = ["Foo", "Bar"]
更新:这已在 Swift 4.1 中登陆,它是一个美丽的东西!
extension Array: Friendly where Element: Friendly 示例现在按照原始问题中给出的方式进行编译。
【问题讨论】:
-
这似乎在 Swift 3.0 的愿望清单上,比较 github.com/apple/swift-evolution/blob/master/README.md: "... 使受约束的扩展符合新协议的能力(即 Equatable 元素的数组是平等的)...”