Why can't Swift automatically convert a generi

2020-04-11 01:04发布

问题:

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?

回答1:

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.



回答2:

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?