mih*_*iho 18 inheritance side-effects kotlin
我刚开始探索Kotlin语言.我正在努力进行遗传,变异和副作用.
如果我宣布一个特质A与val x和覆盖x在AImpl它可以覆盖它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默认为.
另外,如果你需要重写一个val有var,但不希望的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中是可选的,可以完全省略它们