尝试实现利用Scala线性化的结构,我们发现了一些我们无法理解的行为。
如果将覆盖的字段设置为def
,一切都按预期进行,如果我们将其设置为lazy val
,它会以无限递归循环崩溃。
使用defs的代码:
trait T {
def fields: List[Int] = Nil
}
trait A extends T {
override def fields = 1 :: super.fields
}
trait B extends T {
override def fields = 2 :: super.fields
}
val x = new B with A
println(x.fields)
lazy vals的代码:
trait T {
def fields: List[Int] = Nil
}
trait A extends T {
override lazy val fields = 1 :: super.fields
}
trait B extends T {
override lazy val fields = 2 :: super.fields
}
val x = new B with A
println(x.fields)
为什么会这样?
答案 0 :(得分:4)
我认为这与https://issues.scala-lang.org/browse/SI-3167
的情况相同Scala编译器错误:可堆叠的特征和延迟的vals导致 StackoverflowException
trait Thing { def name: String }
trait Thing1 extends Thing { override lazy val name = "One" }
trait Thing2 extends Thing { abstract override lazy val name = super.name }
val t = new Thing with Thing1 with Thing2
t.name
结果为java.lang.StackOverflowError
。
你可以使它更相似。
trait Thing { def name: String = "" }
trait Thing1 extends Thing { override lazy val name = "One" }
trait Thing2 extends Thing { override lazy val name = super.name }
val t = new Thing with Thing1 with Thing2
t.name
这也会产生java.lang.StackOverflowError
。
无论如何,这个bug修复是他妈的推迟了。
Added the Fix Version 'Scala 2.11.3'
Removed the Fix Version 'Scala 2.11.2'
Added the Fix Version 'Scala 2.11.2'
Removed the Fix Version 'Scala 2.11.1'
Added the Fix Version 'Scala 2.11.1-RC1'
Removed the Fix Version '2.11.1-RC1'
Added the Fix Version '2.11.1-RC1'
Removed the Fix Version 'Scala 2.11.0-RC1'
Added the Fix Version 'Scala 2.11.0-RC1'
Removed the Fix Version 'Scala 2.11.0-M8'
Added the Fix Version 'Scala 2.11.0-M8'
Removed the Fix Version 'Scala 2.11.0-M7'
Added the Fix Version 'Scala 2.11.0-M6'
Removed the Fix Version 'Scala 2.11.0-M4'
Added the Fix Version 'Scala 2.11.0-M4'
Removed the Fix Version 'Scala 2.11.0-M3'
Added the Fix Version 'Scala 2.11.0-M3'
Removed the Fix Version 'Scala 2.11.0-M2'
...
2010年报道了这个问题。
我建议不要使用在可堆叠特征中调用lazy val
的{{1}}。