2015-09-18 5 views
1

Почему это не работает (даже если контейнер соответствует уникальному протоколу.) И как будет выглядеть наилучшее обходное решение?Swift 2.0: невозможно передать общий параметр в качестве параметра

protocol Unique { 
    var uniqueId: String {get} 
} 

struct Container <T>: Unique { 
    typealias UnderlyingObject = T 
    var object: UnderlyingObject 
    var uniqueId: String 
} 

func myFunc(protocolClosure: (Unique, Unique) -> Unique) { 
    print("...") 
} 

func problemStartsHere<T,S,U>(paramClosure: (Container<T>, Container<S>) -> Container<U>) { 
    myFunc(paramClosure) 
} 

enter image description here

+1

Я думаю, что это проблема ковариации/контравариантности общего типа, однако я не пользователь Swift, поэтому я не могу быть более конкретным. – Dai

ответ

1

Компилятор показывает это предупреждение по какой-либо причине: myFunc ожидает закрытия, которое работает для любого вида Unique не только Container<T>.

Вы должны использовать общую версию функции вместо:

func myFunc<A: Unique, B: Unique, C: Unique>(protocolClosure: (A, B) -> C) { 
    print("...") 
} 

EDIT: Предположим, вы хотите назвать вашу функцию problemStartsHere так:

problemStartsHere { (c1: Container<Int>, c2: Container<Int>) -> Container<Int> in 
    print(c1.object, c2.object) 
    return c1 
} 

Обратите внимание, что функция использует Container - специфическое свойство object. Не так, как именно компилятор должен создать закрытие, которое работает на любом Unique? Он не может работать так, потому что это не имеет смысла, такая функция не может работать ни на одном Unique.

+0

Причина для меня нелогична. Любой Контейнер уже уникален, так почему бы не принять его? –

+0

@purrrminator Отредактировал мой ответ – Kametrixom

1

Проблема здесь одна из дисперсии, хотя и не совсем дисперсия вы ищете. Поскольку вы проходите закрытие, вы действительно пытаетесь совместить подпись метода, а не значение, переданное или возвращаемое из самого метода. Это может вызвать проблемы, если, скажем, myFunc попытался вызвать замыкание с использованием параметра типа, отличного от Container<T>, - и поскольку он ожидает, что любой Unique будет приемлемым для этого вызова, он будет скомпилировать только штраф.

+0

Итак, как бы выглядело самое лучшее обходное решение? –

+0

Проблема с ответом на эту часть вопроса @purrrminator заключается в том, что я не делаю этого и никогда не программировал в Swift, но знаю, что это основано на механике C#, чтобы это много узнать. – David

1

Проблема - это возвращаемое значение. В то время как вы можете передать любой параметр Container<...> в Unique, возвращаемое значение типа Unique не может быть отнесено к Container<...>. Вот почему тип замыкания (Container<...>, Container<...>) -> Container<...> не может быть отлит до (Unique, Unique) -> Unique.

Смежные вопросы