2

I have the following class:

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

I receive a pre-compilation error stating:

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

To fix this pre-compilation error I am casting the ViewIntent object to I:

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

But why can't Kotlin detect that I must be derived from ViewIntent and smart cast it?

4

3 回答 3

8

那是因为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
    }
}
于 2018-06-05T18:14:14.543 回答
5

只是因为“I”不一定是从 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

于 2018-06-05T18:12:28.593 回答
1

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

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

return object : I {}

在我们I用一个实际的类替换它,

return object : SomeClass {}

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

于 2019-01-24T21:39:32.673 回答