为什么Kotlin不能在接口和从它派生的泛型类型之间进行智能转换?

S-K*_*-K' 2 kotlin kotlin-generics

我有以下课程:

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

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

Type mismatch
Required: I
Found: <S, I>
Run Code Online (Sandbox Code Playgroud)

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

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

但为什么Kotlin不能检测到I必须从中衍生出来ViewIntent并且聪明地施展它?

Ego*_*uba 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
    }
}
Run Code Online (Sandbox Code Playgroud)


Ray*_*aga 5

这只是因为"我"不一定是从ViewIntent派生出来的,而是ViewIntent类.

你可以像这样解决它:

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

按自己的方式行事真的不安全.

为了理解原因,我想你应该开始阅读:

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