那么你可以安全地使用delayedInit吗?

时间:2013-09-03 01:16:27

标签: scala

在阅读了有关delayedInit的各种帖子之后,我惊讶地发现每次在构造过程中都会被各个子类调用。我不确定我是否相信这一点,但后来我在下面进行了测试。无论如何,我的问题是delayedInit听起来像一个有用的机制来从抽象类驱动某种最终操作(例如,可能通知另一个创建对象完成)。如果只调用一次,这就有意义了。 但是,如果你冒险重复调用而没有在其参数中传递任何其他有用信息,那么如何从函数中创建任何类型的有用构造?我怎么能把它编程为仅在最后一级施工中开火,而不必知道A级的延伸程度如何?

object LearnDelayedInit extends App {

  class A extends DelayedInit {
    def delayedInit(x: => Unit) {
      x  // call constructor code
      println("delayed init called")
    }
  }

  class B extends A {        
    println("Hello from B")    
  }

  class C extends B {    
    println("hello from C")
  }

  val c = new C    
}

输出:

Hello from B    
delayed init called    
hello from C    
delayed init called

2 个答案:

答案 0 :(得分:3)

如果您使用特征构建层次结构,并且只有叶子类型为类,您将获得所需的行为:

object LearnDelayedInit extends App {

  trait A extends DelayedInit {
    def delayedInit(x: => Unit) {
      x  //call constructor code
      println("delayed init called")
    }
  }

  trait B extends A {
    println("Hello from B")
  }

  class C extends B {
    println("hello from C")
  }

  val c = new C
}

只有类的初始化代码被包装并传递给delayedInit,traits像往常一样在构造函数中运行它们的初始化代码。

答案 1 :(得分:1)

你走了。

未来的东西只是为了天赋。

基本思想是val done只在C的初始化程序或底层类的初始值中初始化一次。

我想在The One Question FAQ中读过一个问题。

object Test extends App {

  import java.util.concurrent.{ CountDownLatch => Latch }

  trait FutureInit {
    import concurrent._
    import ExecutionContext.Implicits._
    private var fs = future(())
    def done: Boolean
    val latch = new Latch(1)
    def delayedInit(x: => Unit) {
      fs = fs andThen {
        case _ =>
          x
          if (done) { println("All done!") ; latch.countDown() }
      }
    }
  }

  class A extends DelayedInit with FutureInit {
    println("Hello from A")
    Thread sleep 500L
    override val done = true
  }

  class B extends A {
    println("Hello from B")
    Thread sleep 500L
    override val done = true
  }

  class C extends B {
    println("hello from C")
    Thread sleep 500L
    override val done = true
  }

  val c = new C
  c.latch.await()
  println("Good bye.")

  val b = new B
  b.latch.await()
  println("That's all, folks. Go home.")
}