You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中重写变量为何获取错误值?继承初始化问题咨询

为什么创建B对象会输出a=0和b=3?

这是Scala类初始化顺序和val/lazy val特性共同导致的结果,咱们一步步拆解来看:

先搞懂Scala子类对象的初始化流程

当你创建子类B的对象时,Scala的执行顺序是固定的:

  • 先跑父类A的全部构造逻辑(包括字段初始化、代码块、println这些语句)
  • 等父类构造完,才会执行子类B的字段赋值和构造逻辑

逐个分析变量的输出原因

1. 普通val a输出0的真相

  • 你在子类B中用override val a = 4重写了父类A的val a = 3
  • 当父类A的构造开始执行时,子类B的a还没来得及赋值(子类初始化在父类之后),所以它暂时是int类型的默认值0
  • 重点:Scala中,只要子类重写了val,父类里对这个val的引用会直接指向子类的版本!所以父类的println("a = " + a)访问的是子类还没初始化的a,自然输出0
  • 等父类构造完,子类才会把a设为4,但这时候父类的println早就执行完了,你看不到这个值

2. lazy val b输出3的原因

  • 懒加载val的核心特性是:第一次被访问的时候才会执行赋值操作
  • 父类A的lazy val b = 2被子类B的override lazy val b = 3重写了
  • 当父类构造中的println("b = " + b)执行时,这是第一次访问b字段,直接触发子类的lazy val初始化,赋值为3并输出,完全跳过了父类的b=2

怎么得到你预期的a=3和b=2?

如果你想让父类使用自己的字段,不让子类重写,可以把父类的字段标记为private[this],这样子类无法重写它,父类访问的就是自己的版本:

class A {
  private[this] val a = 3
  private[this] lazy val b = 2
  println("a = " + a)
  println("b = " + b)
}

class B extends A {
  val a = 4 // 这是子类自己的字段,不再是重写父类的
  lazy val b = 3
}

此时创建B的对象,就会输出你预期的结果啦。

内容的提问来源于stack exchange,提问作者himanshuIIITian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:57:33