在阅读了有关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
答案 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.")
}