Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

swift - extend generic Array<T> to adopt protocol

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can extend SequenceType instead of Array

extension SequenceType where Generator.Element == Float {
//
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...