类似于Equatable的Swift协议

Dav*_*rns 3 cocoa swift swift-protocols

我正在尝试为Lerp-able(线性插值)类型创建一个协议.我声明它与Equatable定义方式类似:

protocol Lerpable {
    func lerp(from: Self, to: Self, alpha: Double) -> Self
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,当我试图实现LerpableDouble:

func lerp(from: Double, to: Double, alpha: Double) -> Double {
    return from + alpha * (to - from)
}
extension Double: Lerpable {}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误:Type 'Double' does not conform to protocol 'Lerpable'.

我认为这将非常简单,但也许我只是不明白Equatable的工作原理.或者它是Swift中的特例?有什么想法吗?


更新:正确答案如下,这是代码的最终版本,供其他人参考:

protocol Lerpable {
    func lerp(to: Self, alpha: Double) -> Self
}

extension Double: Lerpable {
    func lerp(to: Double, alpha: Double) -> Double {
        return self + alpha * (to - self)
    }
}

func lerp<T: Lerpable>(from: T, to: T, alpha: Double) -> T {
    return from.lerp(to, alpha: alpha)
}
Run Code Online (Sandbox Code Playgroud)

我添加了全局lerp函数,所以我仍然可以将其称为
lerp(foo, bar, alpha: 0.5)
而不是
foo.lerp(bar, alpha: 0.5)

ABa*_*ith 5

要解决您的问题,您需要将lerp功能放在您的内部extension,如下所示:

extension Double: Lerpable {
    func lerp(from: Double, to: Double, alpha: Double) -> Double {
        return from + alpha * (to - from)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你看看Equatable protocol:

protocol Equatable {
    func == (lhs: Self, rhs: Self) -> Bool
}
Run Code Online (Sandbox Code Playgroud)

您在其==类型之外声明其方法(特别是)的原因extension是因为Equatable您希望重载运算符,并且必须在全局范围内声明运算符.这是一个澄清的例子:

protocol MyProtocol {
    func *** (lhs: Self, rhs: Self) -> Self
}
Run Code Online (Sandbox Code Playgroud)

现在Int采用协议:

extension Int : MyProtocol {}

infix operator *** {}
func *** (lhs: Int, rhs: Int) -> Int {
    return lhs * rhs
}
Run Code Online (Sandbox Code Playgroud)