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
相关产品推荐
相关产品推荐

