1

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

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

有没有办法做到这一点?

4

2 回答 2

1

您需要在 B 中使用惰性 val,或使用“早期初始化程序”,以便 B 中的 val 在 A 中的 val 之前初始化。以下是对这两个选项如何工作的精彩描述:https://github。 com/paulp/scala-faq/wiki/Initialization-Order

于 2012-04-28T16:27:17.877 回答
0

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

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
于 2012-04-29T06:32:29.857 回答