2016-07-31 2 views
0

Я пытаюсь написать базовую функцию интерполяции в swift3. Я получаю много ошибок. Это, очевидно, не правильный способ использования дженериков, но, возможно, у меня есть фундаментальное непонимание их применения?Как написать функцию, которая принимает общие аргументы типа, но возвращает другой тип в зависимости от типа общего объекта?

class func interpolate<T>(from: T, to: T, progress: CGFloat) -> T 
{ 
    // Safety 
    assert(progress >= 0 && progress <= 1, "Invalid progress value: \(progress)") 

    if let from = from as? CGFloat, let to = to as? CGFloat 
    { 
     return from + (to - from) * progress // No + candidates produce the expected contextual result type 'T' 
    } 
    if let from = from as? CGPoint, let to = to as? CGPoint 
    { 
     var returnPoint = CGPoint() 
     returnPoint.x  = from.x + (to.x-from.x) * progress 
     returnPoint.y  = from.y + (to.y-from.y) * progress 
     return returnPoint // Cannot convert return expression of type 'CGPoint' to return type 'T' 
    } 
    if let from = from as? CGRect, let to = to as? CGRect 
    { 
     var returnRect = CGRect() 
     returnRect.origin.x  = from.origin.x + (to.origin.x-from.origin.x) * progress 
     returnRect.origin.y  = from.origin.y + (to.origin.y-from.origin.y) * progress 
     returnRect.size.width = from.size.width + (to.size.width-from.size.width) * progress 
     returnRect.size.height = from.size.height + (to.size.height-from.size.height) * progress 
     return returnRect // Cannot convert return expression of type 'CGRect' to return type 'T' 
    } 

    return nil // Nil is incompatible with return type 'T' 
} 
+5

Пробовали ли вы общий подход, предложенный в http://stackoverflow.com/questions/38652237/how-can-i-handle-different-types-using-generic-type-in -swift? –

+0

Этот ответ был просто более длинным способом расширения классов, в которых я забочусь о том, чтобы использовать функцию интерполяции, и это то, что я делаю сейчас как меру остановки. Он также не ответил на вопрос, почему то, что я пробовал, не работает. – GoldenJoe

ответ

2

Общая функция полезна, когда вы выполняете одни и те же операции на нескольких разных типах. Это в основном то, что у вас здесь. Проблема в том, что у вас нет операций, определенных для двух типов, которые вас волнуют, а именно: CGPoint и CGRect.

Если вы создаете отдельные функции для добавления, вычитания и умножения этих типов, вы можете заставить эту общую функцию работать. Было бы упрощена до

class func interpolate<T>(from: T, to: T, progress: CGFloat) -> T 
{ 
    // Safety 
    assert(0.0...1.0 ~= progress, "Invalid progress value: \(progress)") 

    return from + (to - from) * progress 
} 
+0

Было бы плохой шаблон, чтобы просто перегрузить операторы + и - в классе интерполяции, чтобы я мог использовать эту упрощенную версию? Есть ли способ безопасно вырваться, если тип, переданный внутри, не поддерживает операторов? – GoldenJoe

+0

Редактировать: Nevermind, пытаясь перегрузить операторы, дает мне: // Нет + кандидаты производят ожидаемый контекстуальный тип результата 'T' – GoldenJoe