【问题标题】:Why can't Kotlin smart cast between an interface and the generic type that is derived from it?为什么 Kotlin 不能在接口和派生自它的泛型类型之间进行智能转换?
【发布时间】:2019-01-25 05:39:32
【问题描述】:

我有以下课程:

abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
    open fun initViewIntent(): I {
        return object : ViewIntent{} // type mismatch on this line
    }
}

我收到一个预编译错误说明:

Type mismatch
Required: I
Found: <S, I>

为了修复这个预编译错误,我将 ViewIntent 对象转换为 I:

abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
    open fun initViewIntent(): I {
        @Suppress("UNCHECKED_CAST")
        return object : ViewIntent{} as I
    }
}

但为什么 Kotlin 不能检测到 I 必须从 ViewIntent 派生并智能转换它?

【问题讨论】:

  • I 派生自 ViewIntent 不足以 使其成为有效的演员表。事实上,ViewIntent 必须派生自 I 才能使您所描述的东西起作用。

标签: kotlin kotlin-generics


【解决方案1】:

那是因为 ViewIntent 不是 I。见例子:

class MyViewIntent : ViewIntent

class MyPresenterActivity : PresenterActivity<..., MyViewIntent>() {
    // inherited from PresenterActivity
    open fun initViewIntent(): ViewIntent {
        return object : ViewIntent{} as MyViewIntent // you see where this breaks
    }
}

【讨论】:

    【解决方案2】:

    只是因为“我”不一定是从 ViewIntent 派生的,而恰恰是 ViewIntent 类。

    你可以这样修复它:

    abstract class PresenterActivity<S : ViewState, I : ViewIntent> : AppCompatActivity() { 
        open fun initViewIntent(): ViewIntent {
            return object : ViewIntent{} 
        }
    }
    

    按你的方式做真的很不安全。

    要了解原因,我想您应该开始阅读以下内容:

    https://blog.kotlin-academy.com/kotlin-generics-variance-modifiers-36b82c7caa39

    https://kotlinlang.org/docs/reference/generics.html

    https://proandroiddev.com/understanding-generics-and-variance-in-kotlin-714c14564c47

    【讨论】:

      【解决方案3】:

      基本上,您所做的事情不起作用的原因是因为IViewIntent 的子类。您的对象也是ViewIntent 的子类。这是一个完全不同的子类。你正在做的演员就像试图将StringBuilder转换成String

      现在让我们讨论一下我认为您“想要”做什么以及为什么这也不起作用。为了真正得到你想要的结果,你需要直接创建I类型,像这样:

      return object : I {}
      

      我们用一个实际的类替换了 I

      return object : SomeClass {}
      

      这当然也会失败。 SomeClass 的构造函数需要被调用,而你没有这样做。并且在使用泛型类型时无法知道将什么传递给该构造函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多