我有以下课程:
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
}
}
但为什么科特林无法检测到I
必须来自ViewIntent
并且聪明地施展它?
答案 0 :(得分: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
}
}
答案 1 :(得分:5)
这只是因为&#34;我&#34;不一定是从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
答案 2 :(得分:1)
基本上,您正在执行的操作不起作用的原因是,I
是ViewIntent
的子类。您的对象也是ViewIntent
的子类。这是一个完全不同的子类。您正在执行的强制转换就像尝试将StringBuilder
强制转换为String
。
现在让我们讨论一下我认为您“想”做的事情以及为什么这也不起作用。为了真正获得所需的结果,您需要直接创建I
类型,如下所示:
return object : I {}
然后我们将I
替换为实际的类,
return object : SomeClass {}
这当然也会失败。 SomeClass
的构造函数需要被调用,而您没有这样做。而且,没有办法知道使用泛型类型时要传递给该构造函数的内容。