在Kotlin中使用泛型边界声明类属性的正确方法是什么?

问题描述 投票:1回答:2

我有这样的界面:

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属性的正确方法是什么?

generics kotlin
2个回答
1
投票

继恒星投影的Kotlin reference之后:

对于Foo<in T>,其中T是逆变型参数,Foo<*>相当于Foo<in Nothing>。这意味着当Foo<*>未知时,你无法以安全的方式写入T

出现错误信息是因为ItemClickListener<in T: Item>的星形投影是ItemClickListener<in Nothing>,无法使用任何参数调用。 This question也提供相关信息。

解决方案是将字段itemClickListenersetOnClickListener的参数声明为ItemClickListener<Item>,它将具有与类声明<in Item>相同的方差。因此,您可以使用onClick的任何子类型调用Item


1
投票

你只需要使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>

© www.soinside.com 2019 - 2024. All rights reserved.