2016-11-14 7 views
2

最善の方法は、この例である、特殊なものを呼び出す一般的な機能書き込む方法:このコードを書くためにどのようにSWIFT:私が欲しいものを記述するための

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 
    } 
} 

、私はCGFloatためlerpKeyframes(...)を使用することができますが、CGPointCGRect

+1

これは失敗します。 'leap'関数特化がない他のLerpable型の場合はどうでしょうか? – Alexander

答えて

4

関連する自己要件とプロトコルが来る場所です。ここラフ例を示します。 'T'は `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) 
} 
+0

あなたは[this](http://codereview.stackexchange.com/questions/146736/adding-swipe-support-to-multiple-classes)でも答えられると思います –

+0

あなたはそれを何と考えていますか? :p – Alexander

+0

どちらも関連しています。私は似たような種類の問題を探していました。 –

関連する問題