2016-03-08 2 views
4

Вот пример того, что я хотел бы достичь:Swift Ковариантных Дженерик

protocol SomeType {} 

class SomeClass: SomeType {} 

struct SomeGenericStruct<A> { 
    typealias E = A 
} 

func take(someType: SomeGenericStruct<SomeType>) {} 

let concreteGenericStruct1: SomeGenericStruct<SomeType> = SomeGenericStruct<SomeType>() 
let concreteGenericStruct2: SomeGenericStruct<SomeClass> = SomeGenericStruct<SomeClass>() 

take(concreteGenericStruct1) 
take(concreteGenericStruct2) // much no work, very repair. wow. 

Или еще проще:

let concreteGenericStruct3: SomeGenericStruct<SomeType> = SomeGenericStruct<SomeClass>() as SomeGenericStruct<SomeType> // still no work 

Как я могу управлять, чтобы обеспечить take с concreteGenericStruct2?

+0

Вы не можете. Как вы заметили, быстрые дженерики не ковариантны. (Массивы ковариантны, но компилятор делает для них особый случай, вы не можете воссоздать это.) Подход Антона, вероятно, лучше всего подходит для вашего точного вопроса, но, скорее всего, вам нужно переосмыслить, как вы приближаетесь к своим данным, и в частности избегайте подклассификации (что является общей причиной желания ковариации, хотя вы демонстрируете ее здесь с помощью протоколов). –

ответ

5

Вы можете использовать универсальный метод для этого:

func take<T where T: SomeType>(someType: SomeGenericStruct<T>) { } 

Единственная проблема состоит в том, что вы не можете передать SomeGenericStruct<SomeType> к нему. Вместо этого он должен быть общим конкретным типом. Если это абсолютно необходимо, вы можете просто иметь две функции, делающие одно и то же: по существу:

func take(someInput: SomeGenericStruct<SomeType>) { /* do stuff */ } 
func take<T where T: SomeType>(someType: SomeGenericStruct<T>) { /* do same stuff */ } 
Смежные вопросы