当覆盖val在Scala中遇到DelayedInit时,奇怪的初始化

时间:2013-07-18 07:16:09

标签: scala init

以下代码的输出让我感到困惑。

object Test1 {
  trait A {
    val s: String = "A"
    println(s"s = $s")
  }

  abstract class B extends A with DelayedInit {

    override def delayedInit(body: => Unit) = {
      println("B " + "1" * 80)
      body
      println("B " + "2" * 80)
    }
  }

  abstract class C extends A with DelayedInit {

    override val s: String = "C"

    override def delayedInit(body: => Unit) = {
      println("C " + "1" * 80)
      body
      println("C " + "2" * 80)
    }
  }

  def main {
    println("-- new B begin")
    new B {
      println("new B context")
    }
    println("-- new B end")

    println("-- new C begin")
    new C {
      println("new C context")
    }
    println("-- new C end")
  }
}

object Test2 {
  trait A {
    def s: String = "A"
    println(s"s = $s")
  }

  abstract class B extends A with DelayedInit {

    override def delayedInit(body: => Unit) = {
      println("B " + "1" * 80)
      body
      println("B " + "2" * 80)
    }
  }

  abstract class C extends A with DelayedInit {

    override def s: String = "C"

    override def delayedInit(body: => Unit) = {
      println("C " + "1" * 80)
      body
      println("C " + "2" * 80)
    }
  }

  def main {
    println("-- new B begin")
    new B {
      println("new B context")
    }
    println("-- new B end")

    println("-- new C begin")
    new C {
      println("new C context")
    }
    println("-- new C end")
  }
}

println("Test1")
Test1.main
println("Test2")
Test2.main

输出

Test1
-- new B begin
s = A
B 11111111111111111111111111111111111111111111111111111111111111111111111111111111
new B context
B 22222222222222222222222222222222222222222222222222222222222222222222222222222222
-- new B end
-- new C begin
s = null
C 11111111111111111111111111111111111111111111111111111111111111111111111111111111
C 22222222222222222222222222222222222222222222222222222222222222222222222222222222
C 11111111111111111111111111111111111111111111111111111111111111111111111111111111
new C context
C 22222222222222222222222222222222222222222222222222222222222222222222222222222222
-- new C end
Test2
-- new B begin
s = A
B 11111111111111111111111111111111111111111111111111111111111111111111111111111111
new B context
B 22222222222222222222222222222222222222222222222222222222222222222222222222222222
-- new B end
-- new C begin
s = C
C 11111111111111111111111111111111111111111111111111111111111111111111111111111111
new C context
C 22222222222222222222222222222222222222222222222222222222222222222222222222222222
-- new C end

尝试了scala 2.10.2& 2.11.0-M3。

根据我的理解,Test1应该与Test2相同。这是两个问题:

  • 为什么在Test1.C中调用了两次DelayedInit?没有其他类继承类层次结构中的特征
  • 为什么{1. 1}在Test1.C?

1 个答案:

答案 0 :(得分:1)

  

为什么在Test1.C中调用了两次DelayedInit?没有其他类继承类层次结构中的特征

这看起来像一个bug,尝试将其报告给Scala JIRA。


  

为什么s == null中有Test1.C

我说这是因为

中的val
override val s: String = "C"

由内部变量支持,此变量在C的initializatino期间初始化。由于DelayedInit未捕获traitA的初始化在delayedInit之前执行,即在Cval s之前执行初始化。

(如果有人为这些类发布了反编译的Java代码,那将会很有趣。)