Android-Kotlin-对象必须声明为抽象或实现抽象成员 [英] Android - Kotlin - object must be declared abstract or implement abstract member

查看:117
本文介绍了Android-Kotlin-对象必须声明为抽象或实现抽象成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为RecyclerView设置了一个ItemClickLister,如下所示:

I have set an ItemClickLister for my RecyclerView like this:

ItemClickSupport.addTo(recyclerView!!).setOnItemClickListener(
                    object : ItemClickSupport.OnItemClickListener {
                        override fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?) {
                            val row = recyclerView!!.getChildAt(position)
                            val el = row.findViewById(R.id.active_expandablelayout) as ExpandableLayout

                            if (el.isExpanded) {
                                el.collapse()
                            } else {
                                el.expand()
                            }
                        }
                    }
            )

使用我翻译成Kotlin的ItemClickSupport库.

using the ItemClickSupport library which I translated into Kotlin.

我在object(第2行)上看到一条错误消息:

I get an error on object (line 2) that says:

对象必须声明为抽象或实现抽象成员.

object must be declared abstract or implement abstract member.

我真的是Kotlin的新手,我在SO上也找不到任何解决方案.

I'm really new to Kotlin and I couldn't find any solution here on SO either.

非常感谢您的帮助.

这是我的ItemClickSupport.kt:

class ItemClickSupport private constructor(private val mRecyclerView: RecyclerView) {
    private var mOnItemClickListener: OnItemClickListener? = null
    private var mOnItemLongClickListener: OnItemLongClickListener? = null
    private val mOnClickListener = View.OnClickListener { v ->
        if (mOnItemClickListener != null) {
            val holder = mRecyclerView.getChildViewHolder(v)
            mOnItemClickListener!!.onItemClicked(mRecyclerView, holder.adapterPosition, v)
        }
    }
    private val mOnLongClickListener = View.OnLongClickListener { v ->
        if (mOnItemLongClickListener != null) {
            val holder = mRecyclerView.getChildViewHolder(v)
            return@OnLongClickListener mOnItemLongClickListener!!.onItemLongClicked(mRecyclerView, holder.adapterPosition, v)
        }
        false
    }
    private val mAttachListener = object : RecyclerView.OnChildAttachStateChangeListener {
        override fun onChildViewAttachedToWindow(view: View) {
            if (mOnItemClickListener != null) {
                view.setOnClickListener(mOnClickListener)
            }
            if (mOnItemLongClickListener != null) {
                view.setOnLongClickListener(mOnLongClickListener)
            }
        }

        override fun onChildViewDetachedFromWindow(view: View) {

        }
    }

    init {
        mRecyclerView.setTag(R.id.item_click_support, this)
        mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener)
    }

    fun setOnItemClickListener(listener: OnItemClickListener): ItemClickSupport {
        mOnItemClickListener = listener
        return this
    }

    fun setOnItemLongClickListener(listener: OnItemLongClickListener): ItemClickSupport {
        mOnItemLongClickListener = listener
        return this
    }

    private fun detach(view: RecyclerView) {
        view.removeOnChildAttachStateChangeListener(mAttachListener)
        view.setTag(R.id.item_click_support, null)
    }

    interface OnItemClickListener {

        fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)
    }

    interface OnItemLongClickListener {

        fun onItemLongClicked(recyclerView: RecyclerView, position: Int, v: View): Boolean
    }

    companion object {

        fun addTo(view: RecyclerView): ItemClickSupport {
            var support: ItemClickSupport? = view.getTag(R.id.item_click_support) as ItemClickSupport
            if (support == null) {
                support = ItemClickSupport(view)
            }
            return support
        }

        fun removeFrom(view: RecyclerView): ItemClickSupport {
            val support = view.getTag(R.id.item_click_support) as ItemClickSupport
            support?.detach(view)
            return support
        }
    }
}

这是一个截图,显示了整个错误及其发生的位置:

This is a screenshot with the whole error and where it happens:

推荐答案

您的接口和方法签名不匹配.您的界面声明一个功能为:

Your interface and method signatures do not match. Your interface is declaring one function as:

fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)

您将其覆盖为:

fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?)

那些不是相同的方法签名.

Those are not the same method signatures.

如果这是Java接口,则可以在更改可空性时进行覆盖,因为尚不清楚什么是可空性(如果Java代码中没有注释).但是由于将其移植到Kotlin界面,您必须必须使用相同的确切签名覆盖.相反,您将RecyclerView?View?都设置为可空,这导致与原始签名不匹配.将您的替代功能更改为:

If this was a Java interface, you can override while changing nullability because it isn't clear what the nullability is (given no annotations in the Java code). But since you ported it to a Kotlin interface you must override using the same exact signature. You instead made both RecyclerView? and View? nullable which results in a mismatch to the original signature. Change your overridden function to be:

override fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)

由于这是Kotin界面,因此您无法将SAM转换为Lambda,这就是为什么以前提供的其他答案不起作用的原因.如果这是Java接口,则可以执行此操作.您可以在 KT-7770 中跟踪Kotlin界面的SAM转换.

Since this is a Kotin interface, you cannot use the SAM conversion to a Lambda so that is why the other answer previously provided does not work. If this was a Java interface, you could do that. You can track SAM conversions for Kotlin interfaces in KT-7770.

如果您希望此代码更惯用Kotlin,则需要函数引用或lambda,而不是接口,而应该这样做而不是依赖SAM转换.您可以在高阶函数和Lambdas中了解更多信息.这不在您的问题讨论范围之内.

If you wanted this code to be more idiomatic Kotlin you would want function references or lambdas instead of interfaces, and you should just do that instead of relying on SAM conversion. You can read more about that in Higher-Order Functions and Lambdas. This is outside the scope of your question to go into more detail.

这篇关于Android-Kotlin-对象必须声明为抽象或实现抽象成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆