接口中的属性不能有后备字段

时间:2016-12-11 09:24:07

标签: android properties kotlin kotlin-android-extensions

我正在学习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 

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

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

我无法理解错误。它说什么?任何人都可以用简单的语言解释一下吗?

1 个答案:

答案 0 :(得分:9)

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

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

interface A {
    var notifier: Int
}

通常,类中的var属性包含3个组件:用于存储其值的私有backing field,用于写入其的setter方法和用于getter方法的var方法阅读。但是一个接口不能有一个字段(因为实时是痛苦的,如果确实存在,某些数学不会加起来),因此接口中的setter属性只包含2个组件:getter和{{{ 1}}。

如上所述,我们的界面A已声明了两种方法:一个setter和一个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) {}
}

事实证明,如果您只指定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
  • 中声明适当的设定者
  • 使用abstract class代替接口