Scala不允许在特征中定义lazy val的主要原因是特征的混入顺序不确定性。特征是Scala中一种重用代码的机制,可以被类以及其他特征混入。lazy val是一种惰性求值的方式,在首次访问时才会计算值,并在后续访问时直接返回已计算的值。然而,特征的混入顺序是不确定的,这就导致了lazy val的初始化可能会出现问题。
考虑以下示例:
trait A {
lazy val x: Int = 1
def printX(): Unit = {
println(x)
}
}
trait B {
lazy val x: Int = 2
}
class C extends A with B
val c = new C
c.printX()
在上述示例中,类C混入了特征A和B,它们都定义了一个名为x的lazy val。由于特征混入的顺序是不确定的,因此无法确定最终使用的x的值。根据示例中的混入顺序,如果特征A先于特征B被混入,那么x的值将是1;反之,如果特征B先于特征A被混入,那么x的值将是2。这种不确定性会导致程序的行为不可预测。
为了避免这种不确定性,Scala禁止在特征中定义lazy val。如果需要在特征中延迟计算值,可以考虑使用def定义一个无参数方法,并在需要时进行调用。
值得注意的是,Scala中仍然可以在类中定义lazy val,并且在类的继承层次结构中,父类的lazy val会被正确地初始化和共享。这是因为在类中,继承的关系是确定的,不存在特征混入顺序的不确定性。
领取专属 10元无门槛券
手把手带您无忧上云