错误或特征:Kotlin允许在继承中将'val'更改为'var'

mih*_*iho 18 inheritance side-effects kotlin

我刚开始探索Kotlin语言.我正在努力进行遗传,变异和副作用.

如果我宣布一个特质Aval x和覆盖xAImpl它可以覆盖它var(见下面的代码).令人惊讶的是,该print()方法A受到重新分配的影响,x即使它x是一个值A.这是一个错误还是一个功能?

码:

trait A {
  fun print() {
    println("A.x = $x")
  }

  val x : Int;
}

class AImpl(x : Int) : A {
  override var x = x; // seems like x can be overriden as `var`
}

fun main(args: Array<String>) {

  val a = AImpl(2)

  a.print() // A.x = 2

  a.x = 3; // x can be changed

  // even though print() is defined in trait A
  // where x is val it prints x = 3
  a.print() // A.x = 3

}
Run Code Online (Sandbox Code Playgroud)

我知道如果我明确定义a类型A,则不允许更改x:

val a = AImpl(2) : A
a.x = 3 // ERROR: value x cannot be reassigned
Run Code Online (Sandbox Code Playgroud)

但是,正如第一个案例所示,遗传可能会导致明显无意的副作用A.如何保护值不被继承更改?

And*_*lav 29

你可以制作你的val final,即完全禁止覆盖它.如果val在类中定义a ,则final默认为.

另外,如果你需要重写一个valvar,但不希望的setter是公共的,你可以这么说:

override var x = 1
    private set
Run Code Online (Sandbox Code Playgroud)

val用a 覆盖a var 是一个功能.它相当于添加set方法,而在超类中只有一个get方法.这对于实现某些模式非常重要,例如只读接口.

没有办法以val一种允许改变突变而不是改变突变的方式"保护"你的被覆盖final,因为val这并不意味着"不可变引用",而只是"只读属性".换句话说,当你的特征A声明a时val,这意味着通过类型A引用,客户端不能写这个val,没有其他保证,或者确实可能.

PS Semicolons在Kotlin中是可选的,可以完全省略它们