【问题标题】:Why can't Swift automatically convert a generic type parameter to its superclass? [duplicate]为什么 Swift 不能自动将泛型类型参数转换为其超类? [复制]
【发布时间】:2018-06-18 23:18:43
【问题描述】:

在 Swift 中考虑以下内容:

struct GenericStruct<T> {}
class A {}
class B: A {}

func doSomething() -> GenericStruct<A> {
   return GenericStruct<B>()
}

这给出了错误:

无法将GenericStruct&lt;B&gt; 类型的返回表达式转换为GenericStruct&lt;A&gt; 类型的返回表达式

但是BA 的子类。

  • 为什么 Swift 不能将 GenericStruct&lt;B&gt; 转换为 GenericStruct&lt;A&gt;
  • 在这种情况下应该怎么做?

【问题讨论】:

  • B: A 并不暗示Generic&lt;B&gt;: Generic&lt;A&gt;

标签: swift generics


【解决方案1】:

Swift 泛型是不变的,这意味着两个泛型类型是不相关的,即使它们的泛型类型参数具有继承关系。不变的泛型类型不能相互转换,因为它们之间没有继承关系。

这意味着即使BA 的子类,GenericStruct&lt;B&gt;GenericStruct&lt;A&gt; 也完全不相关,因此您不能将一个转换为另一个。

【讨论】:

    【解决方案2】:

    下面是一个反例,说明如果允许这样做会发生什么:

    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?
    

    【讨论】:

    • 这完全是@David_Pasztor 在他的回答中描述的简单代码示例吗?如果是这样,为什么不将其包含在您的答案中?如果没有,请问这段代码显示了什么?
    • 我的回答是对他的补充。他是完全正确的,Swift 的泛型是不变的。在我的回答中,我详细说明了如果允许 OP 的提议,可能会出现哪些无效代码。
    • 我对删除你的答案犹豫不决 - 我已经投票支持另一个。有了你的评论,我也会支持你的。
    • 非常有用的插图,谢谢
    • 考虑到 Swift 中结构的语义,useB 将始终使用存储在 wrapperOfB 中的引用,而不是 wrapperOfA 中的副本,我们分配 C() 的行也会创建 GenericStruct 的新值。方差实际上是一个有效且有用的概念,即使在一些标准的 Swift 类型中也可以看到。
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多