【问题标题】:What's the correct way to declare a class property with generic bounds in Kotlin?在 Kotlin 中声明具有通用边界的类属性的正确方法是什么?
【发布时间】:2018-03-02 17:12:55
【问题描述】:

我有一个这样的界面:

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)

我明白了:

外投影类型 'ItemClickListener?'禁止使用'public abstract fun onClick(item: T): Unit defined in my.package.ItemClickListener'

在我的类上声明 itemClickListener 属性的正确方法是什么?

【问题讨论】:

    标签: generics kotlin


    【解决方案1】:

    按照Kotlin reference 的星星投影:

    对于Foo&lt;in T&gt;,其中T 是逆变类型参数,Foo&lt;*&gt; 等价于Foo&lt;in Nothing&gt;。这意味着当T 未知时,您无法以安全的方式向Foo&lt;*&gt; 写入任何内容。

    出现错误消息是因为ItemClickListener&lt;in T: Item&gt; 的星形投影是ItemClickListener&lt;in Nothing&gt;,不能使用任何参数调用。 This question也给出了相关信息。

    解决方案是将itemClickListener 字段和setOnClickListener 的参数声明为ItemClickListener&lt;Item&gt;,这与类声明&lt;in Item&gt; 具有相同的差异。因此,您可以使用Item 的任何子类型调用onClick

    【讨论】:

    • 谢谢!这就是我最终做的方式:)
    【解决方案2】:

    您也只需将MyClass 设为通用:

    abstract class MyClass<out I : Item> {
        private var itemClickListener: ItemClickListener<I>? = null
    
        fun setOnClickListener(clickListener: ItemClickListener<I>) {
            this.itemClickListener = clickListener
        }
    }
    

    现在itemClickListener 是类型安全的,以后可以用作ItemClickListener&lt;I: Item&gt;

    【讨论】:

      猜你喜欢
      • 2020-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-07
      • 1970-01-01
      • 2019-05-09
      • 2016-03-31
      相关资源
      最近更新 更多