Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 为什么我会得到一个;继承的平台声明冲突“;派生类中的错误?_Android_Kotlin_Derived Class - Fatal编程技术网

Android 为什么我会得到一个;继承的平台声明冲突“;派生类中的错误?

Android 为什么我会得到一个;继承的平台声明冲突“;派生类中的错误?,android,kotlin,derived-class,Android,Kotlin,Derived Class,具有接口(从依赖SDK定义,不能进行更改,BaseDelegate也来自SDK)和基类: interface ViewDelegate { fun getDataType() : String fun getItemViewType() : Int fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder fun onBindViewHolder(holder: RecyclerVie

具有接口(从依赖SDK定义,不能进行更改,BaseDelegate也来自SDK)和基类:

interface ViewDelegate {

    fun getDataType() : String
    fun getItemViewType() : Int

    fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder
    fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: Data, position: Int)

    fun getClickHandler() : View.OnClickListener
    fun setClickHandler(clickHanlder: View.OnClickListener)
}

open class BaseDelegate(@JvmField var clickHandler: View.OnClickListener) : ViewDelegate {

    @JvmField var layoutId = R.layout.base_view

    override fun getClickHandler(): View.OnClickListener {
        return clickHandler
    }

    override fun setClickHandler(clickHanlder: View.OnClickListener) {
        clickHandler = clickHanlder
    }

    override fun getDataType(): String {
        return "Base_TYPE"
    }

    override fun getItemViewType(): Int {
        return 1000
    }

    override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
        return BaseViewHolder(parent.inflate(layoutId, false), clickHandler)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: IData, position: Int) {
        (holder as? BaseViewHolder)?.bindView(item, position)
    }
}
很好

但如果从基类生成派生类,则会出现错误

class DerivedViewDelegate(clickHandler: View.OnClickListener) : BaseDelegate(clickHandler){

    init {
        layoutId = R.layout.child_view
    }

    override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder {
        val vw = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false)
        return ChildViewHolder(vw, clickHandler)
    }
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, item: Data, position: Int) {
        (holder as? ChildViewHolder)?.bindView(item, position)
    }
}
错误显示:

inherited platform declaration clash: The following declarations have same JVM signature (getClickHandler()Landroid/view$OnClickListner;)  fun <get-clickHandler>(): View.OnClickListener defined in DerivedViewDelegate fun getClickHandler(): View.OnClickListener defined in DerivedViewDelegate

inherited platform declaration clash: The following declarations have same JVM signature (setClickHandler(Landroid/view$OnClickListner;)V)  fun <set-clickHandler>(<set-?>: View.OnClickListener): Unit  defined in DerivedViewDelegate fun setClickHandler(clickHandler: View.OnClickListener): Unit defined in DerivedViewDelegate

如果删除
@JvmField
,则主要问题将可见;如果将其从BaseDelegate中删除,则会出现相同的错误

发生的事情是字段创建了自己的getter和setter,这与父类中的方法冲突。在派生类上使用@JvmField不起作用;它仍然显示相同的错误

因此,不是声明getter和setter,而是一个相对简单的解决方案。Kotlin中的接口可以有字段。不管怎样,根据我所知,它们被编译成getter和setter。无论如何,主要的一点是,它允许一种简单的方法来处理接口中所需的变量

因此,将您的界面更改为:

interface ViewDelegate {
    var clickHandler: View.OnClickListener

    fun getDataType() : String
    fun getItemViewType() : Int

    fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder
    fun onBindViewHolder(holder: RecyclerView.ViewHolder, data: ClipData.Item, position: Int)

}
注意,我删除了getter和setter,只是用一个变量替换了它

现在,在BaseDelegate类中,必须重写变量:

class BaseDelegate(override var clickHandler: View.OnClickListener) : ViewDelegate
@JvmField不见了。还记得在类中删除getter和setter,您将不再需要它们。一旦删除了@JvmField,BaseDelegate和ViewDelegate中的getter和setter,除了添加字段外,还应该编译它


因为你不能改变接口(顺便说一句,这是你最好的选择),所以还有另一个选择。私有字段不使用getter和setter,除非它们是显式定义的。举个例子:

class Test(){
    var x: Int = 0
    fun something(){
        x = 3
    }
}
它汇编为:

public final class Test {
   private int x;

   public final int getX() {
      return this.x;
   }

   public final void setX(int var1) {
      this.x = var1;
   }

   public final void something() {
      this.x = 3;
   }
}
请注意x是如何直接引用的。现在,如果我把它保密:

class Test(){
    private var x: Int = 0
    fun something(){
        x = 3
    }
}
发生这种情况:

public final class Test {
   private int x;

   public final void something() {
      this.x = 3;
   }
}
能手和二传手都走了。但是,如果我明确声明:

class Test(){
    private var x: Int = 0
        get() = field
        set(v) {
            field = v;
        }
    fun something(){
        x = 3
    }
}
它产生:

public final class Test {
   private int x;

   private final int getX() {
      return this.x;
   }

   private final void setX(int v) {
      this.x = v;
   }

   public final void something() {
      this.setX(3);
   }
}
公共var也会发生同样的情况;如果getter是声明的并且是自定义的(不仅仅是
get set
),它将使用
.setX(v)
而不是
this.x=v

这对你的情况有何影响

生成的getter和库声明的getter的声明相互冲突。因此,由于除非显式定义了getter和/或setter,否则私有字段不会创建getter和/或setter,因此将您的var更改为私有:

open class BaseDelegate(private var clickHandler: View.OnClickListener) : ViewDelegate

请注意,这会破坏属性访问语法您将无法调用
derivedViewDelegateInst.clickHandler
,您需要使用getter,即使在Kotlin中也是如此

@JvmField
注释添加到构造函数中的
clickHandler
,或将其重命名。@Wnader,class-DerivedViewDelegate(@JvmField-clickHandler2:View.OnClickListener):BaseDelegate(clickHandler2)不起作用,同样的错误谢谢Zoe,但无法更改接口,它来自其他库。我将看看是否可以找到其他替代。库最初是用Kotlin编写的吗?是的,baseDelegate实际上也是来自sdk,只是想覆盖它。我猜@JvmField是Java应用程序用来覆盖它的。第三部分库(我称之为sdk,而不是android库/sdk)
open class BaseDelegate(private var clickHandler: View.OnClickListener) : ViewDelegate