Android 为什么我会得到一个;继承的平台声明冲突“;派生类中的错误?
具有接口(从依赖SDK定义,不能进行更改,BaseDelegate也来自SDK)和基类: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
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