我正在编写一个实现接口的类,该接口公开了setSelected
方法。这个类将有一个selected
属性:
private class Foo : IFoo {
var selected = false
override fun setSelected(isActive: Boolean) {
selected = isActive
}
}
然而编译器抱怨,因为Kotlin为selected
生成了一个setter,这两个方法发生冲突:
Error:(14, 9) Kotlin: [com.bar.jvmTest] Platform declaration clash: The following declarations have the same JVM signature (setSelected(Z)V):
fun <set-selected>(<set-?>: Boolean): Unit defined in foo.bar.baz.Foo
fun setSelected(isActive: Boolean): Unit defined in foo.bar.baz.Foo
Error:(24, 9) Kotlin: [com.bar.jvmTest] Platform declaration clash: The following declarations have the same JVM signature (setSelected(Z)V):
fun <set-selected>(<set-?>: Boolean): Unit defined in foo.bar.baz.Foo
fun setSelected(isActive: Boolean): Unit defined in foo.bar.baz.Foo
override
,所以我的类没有完全实现接口:
Error:(11, 13) Kotlin: [com.bar.jvmTest] Class 'Foo' is not abstract and does not implement abstract member public abstract fun setSelected(isActive: Boolean): Unit defined in bar.baz
selected
重命名为例如dataSelected
以便生成的setter不会与方法冲突,但应该有一种方法来保持这个简单的属性名称并按预期实现接口。override
?您可以创建没有支持字段的属性,然后覆盖您的抽象函数,如下所示:
class Foo : IFoo {
private var hiddenSelected = false
val selected get() = hiddenSelected
override fun setSelected(isActive: Boolean) {
hiddenSelected = isActive
}
}
更新:
在睡觉之后,我认为这个解决方案并不是那么好,原因有两个:
hiddenSelected
),这是不必要的=
运算符)对该字段进行分配我认为最好的解决方案是:
class Foo : IFoo {
@set:JvmName("setSelected0")
var selected: Boolean = false
set(value) { setSelected(value) }
override fun setSelected(isActive: Boolean) {
// Possibly some other stuff
println("Now i'm using my own setter!")
selected = isActive
}
}
使用注释@JvmName,您可以告诉编译器如何命名该特定函数。 Kotlin会自动为每个属性创建一个getter和setter,因此您需要使用set:
修饰符来注释该属性的setter而不是属性本身。
此外,为该属性实现自定义setter非常重要,这样您就可以安全地编写:
Foo().selected = true // This also prints "Now i'm using my own setter!"
而不是这个:
Foo().setSelected(true)
你的setter可能会做一些其他的东西(比如打印日志),这可能有副作用,所以你需要确保你调用正确的setter。这有时候有点棘手,因为Kotlin总是为每个可变变量(var
)创建一个setter。
你可以use @JvmName
to rename the generated setter:
private class Foo : IFoo {
@set:JvmName("setSelected0")
var selected = false
override fun setSelected(isActive: Boolean) {
selected = isActive
}
}
使用Kotlin保持不变。