scala:如何包装子类构造函数的执行?

时间:2011-05-20 23:53:24

标签: scala

在scala中,我有一个基类和一些子类。在不向子类添加代码或更改子类的实例化的情况下,我希望基类能够在子构造函数执行之前和之后调用某些代码。之前很容易,因为基类构造函数在子项之前被调用,但我没有看到处理后案例的方法。作为一些示例代码:

class A {
  // do some stuff before child constructor is called
  // ...

  // do some other stuff after child constructor is called
  // this could be a method or inline in the constructor, doesn't matter.
}    

class B extends A { // stuff happens in between }

class C extends A { // stuff happens in between }
etc 

val b = new B // everything happens inside, no other method call needed

这种行为可能吗?感谢。

2 个答案:

答案 0 :(得分:4)

如果您使用Scala 2.9,您可以安排以下内容:

class A { 
  println("Hi")
}
class B extends A with DelayedInit {
  private[this] var count = 0
  println("Hey")
  def delayedInit(x: => Unit) {
    x
    count += 1
    if (count==2) { println("There") }
  }
}
class C extends B { println("Ho") }
class D extends C { println("Ha") }

这利用了新的DelayedInit特性,它将延迟的构造函数从当前和所有子类发送到delayedInit方法。不幸的是,由于没有终止信号,你只能跳过一个构造函数。因此对于C,我们得到:

scala> new C
Hi
Hey
Ho
There

其中“There”块在来自C的“Ho”块之后神奇地出现了。不幸的是,如果你扩展C,新的初始化会在最后发生:

scala> new D
Hi
Hey
Ho
There
Ha

(你真的不需要A ......我只是把它放在那里来说明超类会发生什么。)

答案 1 :(得分:0)

可以使用“具体类结束”回调, 下面的代码输出:

hello
world1
world2
world3
end of the worlds !

trait A extends DelayedInit {

  def delayedInit(body: => Unit) = {
    body
    println("end of the worlds !")
  }
}

trait B extends A { println("hello") }
trait C extends B { println("world1") }
trait D extends C { println("world2") }

object Zozo extends  D {
  println("world3")
}