错误或特征:Kotlin允许在继承中将'val'更改为'var' [英] Bug or Feature: Kotlin allows to change 'val' to 'var' in inheritance
问题描述
我刚刚开始探索Kotlin语言。我正在努力继承遗产,变量和副作用。
I just started to explore the language Kotlin. I'm struggling with inheritance, var&val and side-effects.
如果我宣布一个特质 A
a val x
并在 AImpl
中覆盖 x
这是可能的将其覆盖为 var
(参见下面的代码)。令人惊讶的是, A
中的 print()
方法受到 x $的重新分配的影响c $ c>即使
x
是 A
中的值。这是一个错误还是一个功能?
If I declare a trait A
with a val x
and override x
in AImpl
it is possible to override it as var
(see code below). Surprisingly the print()
method in A
is affected by the reassignment of x
even though x
is a value in A
. Is this a bug or a feature?
代码:
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
}
我知道这个事实如果我明确定义 a
类型 A
,则不允许更改 x
:
I'm aware of the fact that if I define a
with type A
explicitly it is not allowed to change x
:
val a = AImpl(2) : A
a.x = 3 // ERROR: value x cannot be reassigned
但是,正如第一个案例所示,继承会导致副作用,但显然不是打算在 A
中。如何保护值不被继承更改?
But as the first case shows, inheritance can cause side effects which are clearly not intended in A
. How do I protect values from being changed by inheritance?
推荐答案
您可以使 val
final
,即完全禁止覆盖它。
如果在类中定义 val
,默认情况下它是 final
。
You can make your val
final
, i.e. forbid overriding it at all.
If you define a val
in a class, it is final
by default.
另外,如果你需要用 var $ c覆盖
val
$ c>,但不希望setter公开,你可以这么说:
Also, if you need to override a val
with a var
, but do not want the setter to be public, you can say so:
override var x = 1
private set
覆盖 val
var
是一项功能。它相当于添加set方法,而在超类中只有get-method。这对于实现某些模式非常重要,例如只读接口。
Overriding a val
with a var
is a feature. It is equivalent to adding a set-method while in the superclass there was only a get-method. And this is rather important in implementing some patterns, such as read-only interfaces.
没有办法保护你的 val
从允许改变突变的方式被覆盖而不是使 final
,因为 val
不意思是不可变引用,但仅仅是只读属性。换句话说,当您的特征 A
声明 val
时,表示通过类型<的引用code> A 客户端无法写入此 val
,没有其他保证,或者确实可能。
There's no way to "protect" your val
from being overridden in a way that allows changing mutation other than making it final
, because val
does not mean "immutable reference", but merely "read-only property". In other words, when your trait A
declares a val
, it means that through a reference of type A
the client can not write this val
, no other guarantees intended, or indeed possible.
P.S。分号在Kotlin中是可选的,可以完全省略它们
P.S. Semicolons are optional in Kotlin, feel free to omit them altogether
这篇关于错误或特征:Kotlin允许在继承中将'val'更改为'var'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!