Unable to set generic type value

I have a general class - Class1 .

 class Class1<T> { } 

And I have Class2 with variable object1 type Class1 and a generic type of UIView

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

When I create an instance of Class2 and try to assign an instance of object1 type Class1 and a generic type of UITableView , I get an error: "Unable to assign a value of type Class1<UITableView> to enter Class1<UIView> "

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

However, the same logic is used for Array. Why?

enter image description here

+6
source share
1 answer

Let me dwell on the comments of Antonov. The question is when can you use B for A. Usually you can do this when B is a subtype of A. For example, you can assign a UITableView variable of type UIView .

So, when is something a subtype of something else?

For classes, it's simple: if you are a subclass of B from A , B is a subtype of A

For function types, you need to consider argument types and return type. The type of the function F2 is a subtype of the type of the function F1 , if the parameter types F2 s are supertypes of the parameter F1 s, and the type of the return type F2 is a subtype of the return type F1 s. You could say that a function should not require more (i.e., it does not require subtypes as parameters, but may require supertypes) and should not provide less (i.e., it should not return a supertype, but may return a subtype) , since its type is a subtype, the terminology is that the parameter types must be contravariant, and the return type must be covariant.

Example:

 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 

Thus, types F2 , f3 and f4 are subtypes of type F1 s, while types f5 , f6 and f7 are not.

What about generic types? In Swift, custom types with type parameters are all invariant. That is, in your example, the Class1<T2> object cannot be used as the Class1<T1> object, regardless of the relationship between T1 and T2 (unless T1 and T2 are the same type).

However, Swift has some built-in dispersion rules that make your example work with arrays: [UITableView] ( Array<UITableView> ) is a subtype of [UIView] ( Array<UIView> ). Please note that the same is true for options, i.e. UITableView? ( Optional<UITableView> ) is a subtype of UIView? ( Optional<UIView> ). Thus, both arrays and additional modules are covariant with their type parameter.

Further reading:

+1
source

Source: https://habr.com/ru/post/1013517/


All Articles