Generics swift:如何编写调用专用函数的通用函数

Generics swift:如何编写调用专用函数的通用函数,generics,swift3,explicit-specialization,Generics,Swift3,Explicit Specialization,描述我想要什么的最佳方式是通过以下示例: protocol Lerpable { // here should be 'lerp<T: Lerpable>(_ x: CGFloat, _ a: T, _ b: T) -> T' function } extension CGFloat: Lerpable {} extension CGPoint: Lerpable {} extension CGRect: Lerpable {} func lerp(_ x: CGFl

描述我想要什么的最佳方式是通过以下示例:

protocol Lerpable {
    // here should be 'lerp<T: Lerpable>(_ x: CGFloat, _ a: T, _ b: T) -> T' function
}
extension CGFloat: Lerpable {}
extension CGPoint: Lerpable {}
extension CGRect: Lerpable {}

func lerp(_ x: CGFloat, _ a: CGFloat, _ b: CGFloat) -> CGFloat {
    return a * (1.0 - x) + b * x
}

func lerp(_ x: CGFloat, _ a: CGPoint, _ b: CGPoint) -> CGPoint {
    return CGPoint(x: lerp(x, a.x, b.x), y: lerp(x, a.y, b.y))
}

func lerp(_ x: CGFloat, _ a: CGRect, _ b: CGRect) -> CGRect {
    return CGRect(x: lerp(x, a.x, b.x), y: lerp(x, a.y, b.y), width: lerp(x, a.width, b.width), height: lerp(x, a.height, b.height))
}

func lerpKeyframes<T: Lerpable>(_ x: CGFloat, array: [T]) -> T? {
    if x <= 0 {
        return array.first
    }
    else if x >= (array.count - 1) {
        return array.last
    }
    else {
        let leftBound = Int(x)
        let fraction = fmod(x, 1.0)
        return lerp(fraction, array[leftBound], array[leftBound + 1]) // ERROR here, can't recognize implemented 'lerp' method
    }
}
协议可恢复{
//这里应该是'lerp(x:CGFloat,a:T,b:T)->T'函数
}
扩展CGFloat:Lerpable{}
扩展CGPoint:Lerpable{}
扩展CGRect:Lerpable{}
函数lerp(x:CGFloat,a:CGFloat,b:CGFloat)->CGFloat{
返回a*(1.0-x)+b*x
}
函数lerp(x:CGFloat,a:CGPoint,b:CGPoint)->CGPoint{
返回点(x:lerp(x,a.x,b.x),y:lerp(x,a.y,b.y))
}
func lerp(x:CGFloat,a:CGRect,b:CGRect)->CGRect{
返回CGRect(x:lerp(x,a.x,b.x),y:lerp(x,a.y,b.y),宽度:lerp(x,a.width,b.width),高度:lerp(x,a.height,b.height))
}
func-lerpKeyframes(x:CGFloat,数组:[T])->T?{
如果x=(array.count-1){
返回数组.last
}
否则{
设leftBound=Int(x)
设分数=fmod(x,1.0)
返回lerp(分数,数组[leftBound],数组[leftBound+1])//此处出错,无法识别实现的“lerp”方法
}
}

如何编写这段代码,这样我就可以使用
lerpKeyframes(…)
来处理
CGFloat
CGPoint
CGRect

这就是具有相关自我需求的协议。下面是一个粗略的例子:

import Foundation

protocol LinearlyInterpolatable {
    func interpolate(with: Self, by: CGFloat) -> Self;
}

extension CGFloat: LinearlyInterpolatable {
    func interpolate(with other: CGFloat, by k: CGFloat) -> CGFloat {
        return self * (1.0 - k) + other * k
    }
}

extension CGPoint: LinearlyInterpolatable {
    func interpolate(with other: CGPoint, by k: CGFloat) -> CGPoint {
        return CGPoint(
            x: self.x.interpolate(with: other.x, by: k),
            y: self.y.interpolate(with: other.y, by: k)
        )
    }
}

extension CGRect: LinearlyInterpolatable {
    internal func interpolate(with other: CGRect, by k: CGFloat) -> CGRect {
        return CGRect(
            x: self.x.interpolate(with: other.x, by: k),
            y: self.y.interpolate(with: other.y, by: k),
            width: self.width.interpolate(with: other.width, by: k),
            height: self.height.interpolate(with: other.height, by: k)
        )
    }
}

func lerpKeyframes<T: LinearlyInterpolatable>(_ k: CGFloat, array: [T]) -> T? {
    let leftBound = Int(k)
    guard 0 <= leftBound else { return array.first }
    guard leftBound < array.count else { return array.last }

    let fraction = fmod(k, 1.0)

    return array[leftBound].interpolate(with: array[leftBound + 1], by: fraction)
}
<代码>导入基础 协议LinearlyInterpolatable{ func插值(带:Self,by:CGFloat)->Self; } 扩展CGFloat:LinearlyInterpolatable{ func插值(使用其他:CGFloat,按k:CGFloat)->CGFloat{ 返回自*(1.0-k)+其他*k } } 扩展CGPoint:LinearlyInterpolatable{ func插值(使用其他:CGPoint,通过k:CGFloat)->CGPoint{ 返回点( x:self.x.插值(使用:other.x,by:k), y:self.y.插值(使用:其他.y,通过:k) ) } } 扩展CGRect:LinearlyInterpolatable{ 内部func插值(使用其他:CGRect,按k:CGFloat)->CGRect{ 返回CGRect( x:self.x.插值(使用:other.x,by:k), y:self.y.插值(使用:other.y,by:k), 宽度:self.width.interpolate(with:other.width,by:k), 高度:self.height.interpolate(with:other.height,by:k) ) } } func-lerpKeyframes(k:CGFloat,数组:[T])->T?{ 设leftBound=Int(k)
guard 0此操作失败,因为无法保证
T
CGFloat
CGPoint
CGRect
。如果它是其他可恢复类型,没有
leap
函数专门化,该怎么办?我想你可以回答这个问题,是什么让你这么认为的?:pBoth相关..我正在寻找类似的kind问题。@AlexanderMomchliov,谢谢!它能工作。奇怪的是,为什么
func-lerp(\ux:CGFloat,\ua:Self,\ub:Self)->Self
不能工作?在尝试调用此函数时编译时出现错误
使用未解析标识符“lerp”