错误或特征:Kotlin允许在继承中将'val'更改为'var' [英] Bug or Feature: Kotlin allows to change 'val' to 'var' in inheritance

查看:477
本文介绍了错误或特征:Kotlin允许在继承中将'val'更改为'var'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始探索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 即使 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 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆