kotlin - 生成的 setter 与接口方法冲突
问题描述
我正在编写一个实现公开setSelected
方法的接口的类。这个类将有一个selected
属性:
private class Foo : IFoo {
var selected = false
override fun setSelected(isActive: Boolean) {
selected = isActive
}
}
然而,编译器抱怨说,当 Kotlin 为 生成一个 setter 时selected
,这两种方法会发生冲突:
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
为 egdataSelected
以便生成的 setter 不会与方法发生冲突,但是应该有一种方法可以保留这个简单的属性名称并按预期实现接口。
有没有办法让 Kotlin 编译器不为此属性生成设置器,或者将其标记为override
?
解决方案
您可以创建一个没有支持字段的属性,然后像这样覆盖您的抽象函数:
class Foo : IFoo {
private var hiddenSelected = false
val selected get() = hiddenSelected
override fun setSelected(isActive: Boolean) {
hiddenSelected = isActive
}
}
更新:
睡了之后,我认为这个解决方案一点也不好,原因有两个:
hiddenSelected
它引入了一个不必要的新字段 ( )- 您不能使用标准 Kotlin 方式(
=
运算符)对该字段进行分配
我认为最好的解决方案是:
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 而不是属性本身。
此外,为该属性实现自定义设置器非常重要,这样您就可以安全地编写以下代码:
Foo().selected = true // This also prints "Now i'm using my own setter!"
而不是这个:
Foo().setSelected(true)
您的 setter 可能会做一些其他事情(例如打印该日志),这可能会产生副作用,因此您需要确保调用正确的 setter。这有时会有点棘手,因为 Kotlin 总是为每个可变变量 ( var
) 创建一个 setter。
推荐阅读
- sql - Oracle - hh mm ss 到 hh:mm:ss 与一个异国情调
- angular - 如何基于 NgRX 存储数据组成 Angular 守卫
- windows - 配置允许 Kerberos 禁用的加密类型
- java - 将正则表达式 ruby 转换为 java
- reactjs - Express JS 如何将所有 http 流量重定向到 https (Heroku)
- javascript - 用 Puppeteer 提取所有 CSS?
- javascript - Bootpag 添加 li 类和一个类
- react-native - 反应本机捆绑异常 java.lang.IllegalStateException:应为字符串,但在 BundleDeltaClient 为 BEGIN_ARRAY
- r - 按因子拆分数据帧并按因子命名新的df和附加描述,如“new_dataframe(因子)”
- ios - Xcode 10 故事板图像渲染