我有一个抽象的泛型类:
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突出显示被覆盖的功能演员说&#34;此演员阵容永远不会成功&#34;。我尝试使用in Any
,out Any
和*
,但它并不起作用。当我尝试使用*
时,我无法在最初定义它的类中使用getPresenter()
方法。 Android Studio抱怨类型不匹配:需要Nothing?,找到BaseFragment。
在Java中,相同的代码可以完美地工作,我并不认为这将是Kotlin中的一个问题。实现这个的正确方法是什么?
答案 0 :(得分:2)
这里的“施法永远不会成功”警告不正确。警告的正确消息应该是“未经检查的强制转换”,因为此强制转换可能正确也可能不正确,但运行程序无法发现此消息。
答案 1 :(得分:0)
使用BasePresenter<*,*>
。
来自docs:
星突起
有时你想说你对这种类型一无所知 参数,但仍希望以安全的方式使用它。这里安全的方式是 定义这种通用类型的投影,即每个具体的投影 该泛型类型的实例化将是该类型的子类型 投影。
Kotlin为此提供了所谓的星形投影语法:
对于
Foo<out T>
,其中T
是协变类型参数 上限TUpper
,Foo<*>
相当于Foo<out TUpper>
。它 意味着当T
未知时,您可以安全地读取值 来自TUpper
的{{1}}。对于Foo<*>
,其中Foo<in T>
是逆变量 类型参数T
相当于Foo<*>
。它的意思是 当Foo<in Nothing>
出现时,您无法以安全的方式写入Foo<*>
未知。对于T
,其中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<*, *>
。注意:星形投影是 非常像Java的原始类型,但是很安全。