【问题标题】:Can I use property syntax for a Java setter without a corresponding getter?我可以在没有相应 getter 的情况下为 Java setter 使用属性语法吗?
【发布时间】:2021-03-09 20:14:03
【问题描述】:

我有一个带有 setter 的 Java 类,但没有属性的 getter。

class Person {
  private String name;
  public void setName(String name) { this.name = name; }
}

我想使用 .name= 从 Kotlin 分配给它

fun example() {
  val p = Person()
  p.name = "example"
}

我在尝试编译 Kotlin 时收到错误 unresolved reference: name。如果我添加一个 getter,错误就会消失,但是我可以使用 setter 作为属性而不在 Java 中定义一个 getter 吗?我知道我仍然可以从 kotlin 拨打 p.setName("example")

以上是MCVE。 real world 代码是一个 Java 构建器,带有 setter 而不是我想从 Kotlin 中使用的 getter,例如

val widget = WidgetBuilder().apply {
  width = 1  // instead I need .setWidth(1)
  height = 2
  weight = 3
  name = "my widget"
}.build()

【问题讨论】:

    标签: kotlin kotlin-java-interop kotlin1.4


    【解决方案1】:

    不,Kotlin 编译器仅在存在与 setter 具有相同或更高可见性的 getter 时才将其识别为属性。这是因为在 Kotlin 中不存在没有 getter 的属性。 (See last sentence in this section.)

    请注意,如果 Java 类只有一个 setter,则它在 Kotlin 中不会作为属性可见,因为 Kotlin 不支持仅设置属性。

    您可以手动为此类编写扩展属性,使您可以使用属性访问语法,尽管有些人可能会认为为属性使用非功能性 getter 是一种反模式。但是您可以控制扩展属性的可见性,所以可能没问题。

    var WidgetBuilder.width: Int
        @Deprecated("Getter is unsupported.", level = DeprecationLevel.ERROR)
        get() = error("unsupported")
        set(value) { setWidth(value) }
    

    构建器的替代方法是使用您可能在其上设置的所有参数以及默认值创建一个扩展函数。然后,您可以使用named arguments 获得与apply 示例类似的语法。

    FWIW,我只是在使用 Java 构建器时按预期使用链式方法调用。

    【讨论】:

    • 您能否将 getter 标记为已弃用,以更强烈地警告不要使用它?
    • @gidds 好主意,我补充了。然后尝试使用它会给出编译器警告。
    猜你喜欢
    • 2014-05-09
    • 2017-06-11
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    相关资源
    最近更新 更多