如何正确地覆盖返回Kotlin中的泛型类实例的方法
我有一个抽象的泛型类:
abstract class BasePresenter<View, Router> { var view: View? = null var router: Router? = null abstract fun OnStart() abstract fun OnStop() }
我有它的一个子类:
class NewsListPresenter : BasePresenter<NewsListView, MainRouter>() { override fun OnStop() { // } override fun OnStart() { // } }
另外我有一个受保护的抽象方法的类:
protected abstract fun getPresenter() : BasePresenter<Any?, Any?>
我把它覆盖在一个子类中:
override fun getPresenter(): BasePresenter<Any?, Any?> { return NewsListPresenter() as BasePresenter<Any?, Any?> }
Android Studio突出显示了重写的功能强制转换,说“这个转换不会成功”。 我尝试使用in Any
, out Any
和*
,它不起作用。 当我尝试使用*
我无法在最初定义的类中使用getPresenter()
方法。 Android Studio抱怨类型不匹配:required Nothing ?,找到BaseFragment。 在Java中,相同的代码可以完美工作,我不认为这是Kotlin的问题。 什么是正确的方式来实现这个?
在这里“铸造不能成功”的警告是不正确的。 警告的正确信息应该是“未经检查的强制转换”,因为这个转换可能是正确的,但不能通过运行程序来发现。
追踪器中有一个问题 ,实际上前几天已经修复了。 修复将可能使它对Kotlin 1.0.3。
使用BasePresenter<*,*>
。
从文档 :
星预测
有时候你想说,你对类型参数一无所知,但仍然想要以一种安全的方式使用它。 这里的安全方法是定义泛型类型的投影,使得泛型类型的每个具体实例都是该投影的子类型。
Kotlin为此提供了所谓的星形投影语法:
对于
Foo<out T>
,其中T
是具有上限TUpper
的协变类型参数,Foo<*>
相当于Foo<out TUpper>
。 这意味着当T
未知时,可以安全地从Foo<*>
读取TUpper
值。 对于Foo<in T>
,其中T
是逆变类型参数,Foo<*>
相当于Foo<in Nothing>
。 这意味着当T
未知时,您可以以安全的方式写信给Foo<*>
。 对于Foo<T>
,其中T
是具有上限TUpper
的不变类型参数,Foo<*>
相当于读取值的Foo<out TUpper>
,以及写入值的Foo<in Nothing>
。 如果一个泛型类型有多个类型参数,每个类型参数可以独立地进行投影。 例如,如果类型被声明为接口Function<in T, out U>
我们可以想象下面的星型投影:
Function<*, String>
表示Function<in Nothing, String>
;Function<Int, *>
表示Function<Int, out Any?>
;Function<*, *>
表示Function<in Nothing, out Any?>
。 注意:星形投影非常类似Java的原始类型,但安全。