我有这样的界面:
interface ItemClickListener<in T : Item> {
fun onClick(item: T)
}
我的课程有点像这样:
abstract class MyClass {
private var itemClickListener: ItemClickListener<*>? = null
fun <I : Item> setOnClickListener(clickListener: ItemClickListener<I>) {
this.itemClickListener = clickListener
}
}
稍后,如果我想使用该侦听器,它将失败:
itemClickListener?.onClick(item)
我明白了:
Out-projection类型'ItemClickListener <*>?'禁止使用'public abstract fun onClick(item:T):my.package.ItemClickListener'中定义的单位
在我的类上声明onitemClickListener属性的正确方法是什么?
继恒星投影的Kotlin reference之后:
对于
Foo<in T>
,其中T
是逆变型参数,Foo<*>
相当于Foo<in Nothing>
。这意味着当Foo<*>
未知时,你无法以安全的方式写入T
。
出现错误信息是因为ItemClickListener<in T: Item>
的星形投影是ItemClickListener<in Nothing>
,无法使用任何参数调用。 This question也提供相关信息。
解决方案是将字段itemClickListener
和setOnClickListener
的参数声明为ItemClickListener<Item>
,它将具有与类声明<in Item>
相同的方差。因此,您可以使用onClick
的任何子类型调用Item
。
你只需要使MyClass
通用:
abstract class MyClass<out I : Item> {
private var itemClickListener: ItemClickListener<I>? = null
fun setOnClickListener(clickListener: ItemClickListener<I>) {
this.itemClickListener = clickListener
}
}
现在itemClickListener
是类型安全的,可以在以后用作ItemClickListener<I: Item>
。