【问题标题】:How do I override a var in a Kotlin class correctly?如何正确覆盖 Kotlin 类中的 var?
【发布时间】:2020-08-27 13:05:20
【问题描述】:

我正在尝试覆盖类中的值。我有以下代码:

open class Balloon() {
    open var textSize: Float = 20f
    init {
        Log.i("textSize", textSize.toString())
    }
}
    
class BigBalloon(): Balloon() {
    override var textSize = 30f
}

但是,日志会打印出这些值:

第一个日志来自Balloon(),第二个来自BigBalloon()。当我将其覆盖为30 时,它如何打印0.0?我是否错误地实现了所有这些?

【问题讨论】:

  • 我刚刚检查了你的代码,它在println(bb.textSize) 创建了一个val bb = BigBalloon() 后打印了30.0。唯一的区别是我必须删除 init 块,因为我在没有 LogCat 的 Kotlin Playground 中尝试过...
  • 那么这意味着该值被正确覆盖,但不在 init 中?
  • 不要在初始化块/构造函数中使用非最终属性或函数stackoverflow.com/questions/50222139/…

标签: android class kotlin inheritance


【解决方案1】:

通常不鼓励在构造函数中访问抽象方法(在本例中为 getTextSize),因为它可能会导致像您这样的工件。

BigBaloon 属性覆盖实际上做了两件事:

  1. 创建新的内部字段 - BigBaloon.textSize
  2. 覆盖 textSize getter 和 setter 以访问该字段

这有点反直觉,但它不会修改 Baloon.textSize 字段的值,因为 getter/setter 不再使用它,所以它保持不变且无法访问。

您的问题是当 BigBaloons 父 Baloon 正在初始化时,它访问 BigBaloon.textSize,此时尚未初始化,因此它返回零。

【讨论】:

    【解决方案2】:

    Kotlin 的初始化顺序并不是你理解的那样,Base (Balloon) 类的 init 块是在覆盖完成之前调用的。 this answer 对此进行了更好的解释。这是Kotlin docs中给出的初始化顺序。

    将属性放入主构造函数中:

    Balloon(var textSize: Float = 20f) {
        // ...
    }
    

    当你想改变它时,只需将它委托给构造函数即可:

    class BigBalloon: Balloon(30f)
    

    【讨论】:

      猜你喜欢
      • 2021-01-10
      • 2016-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多