No se puede asignar el valor del tipo genérico.

Tengo class genérica – Class1 .

 class Class1<T> { } 

Y tengo Class2 con variable object1 de tipo Class1 y tipo genérico UIView

 class Class2 { var object1: Class1<UIView>? } 

Cuando creo la instancia de Class2 e bash asignar a la instancia de object1 del tipo Class1 y el tipo genérico UITableView , recibí un error: "No se puede asignar el valor de tipo Class1<UITableView> para escribir Class1<UIView> "

 var c = Class2() c.object1 = Class1<UITableView>() 

Sin embargo, la misma lógica funciona para Array. ¿Por qué?

introduzca la descripción de la imagen aquí

Déjame explicarte el comentario de Anton. La pregunta es cuándo puede usar una B para una A. Por lo general, puede hacerlo cuando B es un subtipo de A. Por ejemplo, puede asignar un UITableView a una variable de tipo UIView .

Entonces, ¿cuándo es algo un subtipo de otra cosa?

Para las classs, esto es sencillo: si la subclass B de A , B es un subtipo de A

Para los types de function, debe considerar los types de argumento y el tipo de retorno. Un tipo de function F2 es un subtipo de tipo de function F1 si los types de parameters de F2 son supertypes del parámetro de F1 y el tipo de retorno de F2 es un subtipo del tipo de retorno de F1 . Se podría decir que una function no debe requerir más (es decir, no debe exigir subtypes como parameters, sino que puede requerir supertypes) y no debe proporcionar less (es decir, no debe devolver un supertipo sino que puede devolver un subtipo) para que su tipo sea un subtipo . La terminología es que los types de parameters deben ser contravariantes y el tipo de retorno debe ser covariante .

Ejemplo:

 var f1: UIControl -> UIControl = ... let f2: UIView -> UIControl = ... let f3: UIControl -> UIButton = ... let f4: UIView -> UIButton = ... f1 = f2 // Fine, f2 takes UIView so it also takes UIControl f1 = f3 // Fine, f3 returns UIButton which is a UIControl f1 = f4 // Fine, both of the above let f5: UIButton -> UIControl let f6: UIControl -> UIView let f7: UIButton -> UIView f1 = f5 // Error, couldn't call with a UIControl because f5 demands at least a UIButton f1 = f6 // Error, call would return only a UIView f1 = f7 // Error, both of the above 

Entonces, los types de f2 , f3 y f4 son subtypes de tipo f1 y los types de f5 , f6 y f7 no lo son.

Ahora, ¿qué pasa con los types generics? En Swift, los types personalizados con parameters de tipo son invariantes . Es decir, en su ejemplo, no se puede usar ningún object Class1<T2> object Class1<T1> , sin importar la relación entre T1 y T2 (excepto cuando T1 y T2 son del mismo tipo).

Sin embargo, Swift tiene algunas reglas de varianza incorporadas que hacen que su ejemplo con arreglos funcione: [UITableView] ( Array<UITableView> ) es un subtipo de [UIView] ( Array<UIView> ). Tenga en count que lo mismo es cierto para los opcionales, es decir, UITableView? ( Optional<UITableView> ) es un subtipo de UIView? ( Optional<UIView> ). Entonces, tanto las matrices como los opcionales son covariantes con su parámetro de tipo.

Otras lecturas:

  • Principio de sustitución de Liskov en Wikipedia
  • Mike Ash sobre covarianza y contravarianza