Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 生成的setter与接口方法冲突_Kotlin_Properties_Getter Setter_Generated Code - Fatal编程技术网

Kotlin 生成的setter与接口方法冲突

Kotlin 生成的setter与接口方法冲突,kotlin,properties,getter-setter,generated-code,Kotlin,Properties,Getter Setter,Generated Code,我正在编写一个类来实现一个接口,该接口公开了一个setSelected方法。此类将具有选定的属性: private class Foo : IFoo { var selected = false override fun setSelected(isActive: Boolean) { selected = isActive } } 但是,当Kotlin为所选的生成setter时,编译器抱怨这两种方法冲突: E

我正在编写一个类来实现一个接口,该接口公开了一个
setSelected
方法。此类将具有选定的
属性:

private class Foo : IFoo {
        var selected = false

        override fun setSelected(isActive: Boolean) {
            selected = isActive
        }

    }
但是,当Kotlin为所选的
生成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
  • 我知道我可以将
    selected
    重命名为,例如
    dataSelected
    ,这样生成的setter不会与方法冲突,但应该有一种方法来保持这个简单的属性名,并按预期实现接口。

  • 有没有办法要求Kotlin编译器不为此属性生成setter,或者将其标记为
    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
      }
    }
    
    使用注释可以告诉编译器如何命名该特定函数。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。您可以:


    Kotlin的使用保持不变。

    我在这里看到的问题是,现在对于相同的
    var
    有两个单独的setter,它们可以有不同的实现。您可以将setter设置为私有,但是Kotlin客户端必须调用
    setSelected
    ,而不是
    selected=
    。或者标记
    setSelected
    deprecated,这样它只能通过接口使用,但这对Java客户机不好,如果有的话。
    Foo().setSelected(true)
    
    private class Foo : IFoo {
        @set:JvmName("setSelected0")
        var selected = false
    
        override fun setSelected(isActive: Boolean) {
            selected = isActive
        }
    }