具有接口(从依赖的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
在Java中很好:
class DerivedViewDelegate extends BaseDelegate {
public DerivedViewDelegate(View.OnClickListener clickHandler) {
super(clickHandler);
layoutId = R.layout.child_view;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, Data item, int position) {
((ChildViewHolder )holder).onBindViewHolder(item, position);
}
@NotNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
View vw = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
return new ChildViewHolder(vw, clickHandler);
}
}
答案 0 :(得分:1)
如果删除@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不见了。还要记住,在课堂上删除您的吸气剂和吸气剂,您将不再需要它们。删除@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);
}
}
公共变量也是如此;如果声明了getter并且是自定义的(不仅是get set
),那么它将使用.setX(v)
而不是this.x = v
。
这如何适用于您的情况?
您对生成的getter和库声明的getter有冲突的声明。因此,由于除非明确定义了私有字段,否则私有字段不会创建getter和/或setter,因此请将您的var更改为private:
open class BaseDelegate(private var clickHandler: View.OnClickListener) : ViewDelegate
请注意,这会破坏属性访问语法; ,您将无法调用derivedViewDelegateInst.clickHandler
,并且即使在科特林