有没有办法在Scala中进行子类初始化后调用一些代码?

时间:2012-04-28 14:45:08

标签: scala

我需要在子类已完成所有初始化之后执行一些代码,例如:

abstract class A(a:String) {
  var sum = 0
  def add(n:Int) = { sum += n; sum }
  def verify = if (sum > 10) () else throw new Exception
  ... initialize subclass ...
  verify
}
class B extends A("In A") { 
  val smth = add(50)
  // I want to avoid calling `verify` here
}
val b = new B
println(b.smth) // 50

有办法吗?

2 个答案:

答案 0 :(得分:1)

你需要在B中使用延迟val,或者使用“早期初始化器”,以便在A中的val之前初始化B中的val。这里是对这两个选项如何工作的一个很好的描述:{{3 }}

答案 1 :(得分:0)

所以我似乎找到了答案。我决定使用DelayedInit特征方法 - 我只是执行延迟代码(并计算它执行的次数),然后当我认为我已经看到足够的初始化(扩展中的每个类一个)时执行所需的代码层次)。我将它包装成一个特性:

trait AfterInit extends DelayedInit {
  def afterInit
  private var initCount = 0
  private def getInitNumber(clazz: Class[_]):Int =
    if (clazz.getSuperclass == classOf[java.lang.Object]) 0 else getInitNumber(clazz.getSuperclass) + 1
  final def delayedInit(x: => Unit) {
    x
    initCount += 1
    if (getInitNumber(this.getClass) + 1 == initCount) afterInit
  }
}

用法:

abstract class A(id:String) extends AfterInit {
  var sum = 0
  def add(n:Int) = { sum += n; sum }
  def afterInit = if (sum > 10) () else throw new Exception
}

class B extends A("B") {
  val add1 = add(50)
}
new B // no exception

class C extends A("C") {
  val add2 = add(5)
}
new C // exception is thrown, since the `sum` was too small