This question already has answers here:
How do I store a value of type Class<ClassImplementingProtocol> in a Dictionary of type [String:Class<Protocol>] in Swift?
(2 answers)
Closed 2 years ago.
Consider the following in Swift:
struct GenericStruct<T> {}
class A {}
class B: A {}
func doSomething() -> GenericStruct<A> {
return GenericStruct<B>()
}
This gives the error:
Cannot convert return expression of type GenericStruct<B>
to return type GenericStruct<A>
But B
is a subclass of A
.
- Why can't Swift convert
GenericStruct<B>
to GenericStruct<A>
?
- What should be done in this scenario?
Swift generics are invariant, meaning that two generic types are unrelated even if their generic type parameters have an inheritance relation. Invariant generic types cannot be cast to each other since they have no inheritance relation to each other.
This means that GenericStruct<B>
and GenericStruct<A>
are completely unrelated even if B
is a subclass of A
, hence you cannot cast one to the other.
Here's a counter example as to what could happen if this were allowed:
struct GenericStruct<T> {
let value: T
}
class A {}
class B: A {}
class C: A {}
let wrapperOfB: GenericStruct<B> = GenericStruct(value: B())
let wrapperOfA: GenericStruct<A> = wrapperOfB // Suppose GenericStruct<B> was a subtype of GenericStruct<A>
wrapperOfA.value = C() // C is an A, so this should be legal
useB(wrapperOfB.value) // Now what?