【发布时间】:2015-12-26 21:57:19
【问题描述】:
假设我已经定义了这样一个协议:
protocol EuclideanPoint {
func distance(other: Self) -> Double
func dimension() -> UInt
}
现在我想扩展 [Float] 和 [Double] 以采用该协议。
但是下面的代码:
extension [Float]: EuclideanPoint {
func distance(other: [Float]) {
return Double(zip(self, other).map{a, b in pow(a-b,2)}.reduce(0, combine: +))
}
func dimension() {
return UInt(self.count)
}
}
由于错误而无效
错误:必须在非专用泛型类型“Array”上声明受约束的扩展,并使用“where”子句指定的约束
我发现了类似的问题(如this),但建议的解决方案是使用extension CollectionType where Generator.Element == S { ... },但在这种情况下会导致错误:
错误:协议 'CollectionType' 只能用作通用约束,因为它具有 Self 或关联的类型要求
有什么解决办法吗?
编辑:
使用建议的解决方案:
protocol DoubleConvertibleType {
var doubleValue: Double { get }
}
extension Double : DoubleConvertibleType { var doubleValue: Double { return self } }
extension Float : DoubleConvertibleType { var doubleValue: Double { return Double(self) } }
extension CGFloat: DoubleConvertibleType { var doubleValue: Double { return Double(self) } }
extension Array where Element : DoubleConvertibleType {
func distance(other: Array) -> Double {
return Double(zip(self, other).map{ pow($0.0.doubleValue - $0.1.doubleValue, 2) }.reduce(0, combine: +))
}
func dimension() -> UInt {
return UInt(self.count)
}
}
为[Double] 和[Float] 提供.distance() 和.dimension() 方法。然而,[Double] 或 [Float] 不能用来代替符合 EuclideanPoint 协议所需的东西,从而产生错误:
错误:类型“[Double]”不符合协议“EuclideanPoint”
【问题讨论】:
-
你应该看看这个答案stackoverflow.com/a/28288619/2303865
-
在 Swift 4(今年秋天推出)中,您可以使用
extension Array: EuclideanPoint where Element: DoubleConvertibleType {}。目前这是不可能的。 (见github.com/apple/swift-evolution/blob/master/proposals/…)