13

我正在学习Kotlin。我的代码如下:

   interface BaseLogicDecoupler<A : BaseViewNotifier, B : BaseScreenRouter> {

        var notifier: A?
        var router: B?

        fun attachNotifier(notifier: A?) {
            this.notifier = notifier
        }

        fun detachNotifier() {
            notifier = null;
        }

        fun attachRouter(router: B?) {
            this.router = router
        }

        fun detachRouter() {
            router = null;
        }
    }

但是当我更改它并尝试为如下属性提供访问器时:

var notifier: A?
    get() = notifier 

它不会编译错误说:接口中的属性不能有支持字段

此处的文档中,kotlin 接口可以提供实现,并且可以具有带有访问器的属性。为什么编译失败?

我无法理解错误。它说什么?谁能简单的解释一下?

4

1 回答 1

18

这是一个意想不到的极端案例,感谢您找到它。

让我简要解释一下发生了什么。为了简单起见,我将使用剥离的接口A和类:B

interface A {
    var notifier: Int
}

通常var,类中的属性包括 3 个组件:backing field用于存储其值的私有、setter用于写入它的getter方法和用于读取它的方法。但是一个接口不能有一个字段(因为 live 是痛苦的,如果有的话,一些数学不会加起来),所以var接口中的属性只包含 2 个组件: asetter和 a getter

正如我上面概述的,我们的接口A声明了 2 个方法: asetter和 a getter,两者都没有实现。让我们为其添加一些实现:

interface A2 {
    var notifier: Int
        get() {return 1}
        set(v) {}
}

到目前为止,一切都很好。两种open具有实现的方法,它们都不使用任何字段。但是,如果只声明了其中一种实现呢?

interface A3 {
    var notifier: Int    //ERROR: Property in an interface cannot have a backing field
        get() {return 1}
        //set(v) {}
}

事实证明,如果您只指定 a getter,Kotlin 还会setter为该属性生成一个(默认)。换句话说,A3类似于A4这里:

interface A4 {
    var notifier: Int
        get() {return 1}
        set(v) {field = v}  //Obviously an error
}

这可能是一个错误或预期的行为。这是问题单:https ://youtrack.jetbrains.com/issue/KT-15193

可能的解决方法:

  • 声明一个适当的设置器,如A2
  • 使用 anabstract class而不是接口
于 2016-12-11T10:31:39.933 回答