Let's say I've defined such a protocol:
protocol EuclideanPoint {
func distance(other: Self) -> Double
func dimension() -> UInt
}
Now I'd like to extend [Float]
and [Double]
to adopt that protocol.
But the following code:
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)
}
}
is invalid because of the error
error: constrained extension must be declared on the unspecialized generic type 'Array' with constraints specified by a 'where' clause
I found similar questions (like this), but the suggested solution is to use extension CollectionType where Generator.Element == S { ... }
, but in this context it leads to the error:
error: protocol 'CollectionType' can only be used as a generic constraint because it has Self or associated type requirements
Is there any solution to this?
EDIT:
using the proposed solution:
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)
}
}
gives [Double]
and [Float]
the .distance()
and .dimension()
methods. Yet [Double]
or [Float]
cannot be used in place of something that is required to conform to the EuclideanPoint protocol, producing the error:
error: type '[Double]' does not conform to protocol 'EuclideanPoint'
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…