Ivan
Ivan

Reputation: 23

How to add default implementation using generic protocol extension?

I want to add default implementation for Int/Float/Double value.

protocol ValueLimit {
    associatedtype T where T: Comparable

    func limit(from minValue: T, to maxValue: T) -> T
}

extension ValueLimit {
    func limit(from minValue: T, to maxValue: T) -> T {
        return Swift.max(Swift.min(self as! Self.T, maxValue), minValue)
    }
}

extension Int: ValueLimit {
    typealias T = Int
}

extension Float: ValueLimit {
    typealias T = Float
}

extension Double: ValueLimit {
    typealias T = Double
}

I belive there is a better way, which can simply use empty extension extension Int: ValueLimit {} to do this, without typealias T = Int, but I don't know how to do this.

Upvotes: 0

Views: 222

Answers (2)

Klein Mioke
Klein Mioke

Reputation: 1352

Maybe this would be simpler.

extension Comparable {
    func limit(from minValue: Self, to maxValue: Self) -> Self {
        return Swift.max(Swift.min(self, maxValue), minValue)
    }
}

Upvotes: 1

David Pasztor
David Pasztor

Reputation: 54805

There's no need for an associated type, you can simply use Self in your limit declaration. You can also declare that conforming types need to conform to Comparable as well in the protocol declaration.

Self refers to the current type, so when using it in protocol methods, it refers to the conforming type. This is how standard library protocols such as Equatable and Comparable are implemented as well.

protocol ValueLimit: Comparable {
    func limit(from minValue: Self, to maxValue: Self) -> Self
}

extension ValueLimit {
    func limit(from minValue: Self, to maxValue: Self) -> Self {
        Swift.max(Swift.min(self, maxValue), minValue)
    }
}

extension Int: ValueLimit {}

extension Float: ValueLimit {}

extension Double: ValueLimit {}

Upvotes: 2

Related Questions