在对象/类默认构造函数中干掉样板

时间:2014-02-19 15:06:34

标签: scala refactoring dry

我有这样的事情:

abstract class RunnerBase { def printErrorAndBreak = ... }

object Runner1 extends RunnerBase {
  breakable {
    doSomething
    if (cond1) printErrorAndBreak(...)
  }
}

object Runner2 extends RunnerBase {
  breakable {
    if (cond1) printErrorAndBreak(...)
    something else
  }
}

我想将breakable { ... }部分移到RunnerBase,以便Runner1Runner2看起来像这样:

object Runner1 extends RunnerBase {
  doSomething
  if (cond1) printErrorAndBreak(...)
}

object Runner2 extends RunnerBase {
  if (cond1) printErrorAndBreak(...)
  something else
}

这甚至可能吗?或者是我将子对象逻辑包装在一个run方法中的唯一方法吗?


更新:根据已接受的答案(无论评论如何),为了稳健和简单起见,我决定采用这种方式:

class RunnerBase { def run = breakable _ }
class Runner1 { run { doSmth; if (?) printErrorAndBreak } }
class Runner2 { run { doSmth; if (?) printErrorAndBreak } }

不完美,因为仍有run { ... }次重复,但至少breakablebreak已封装在RunnerBase中。

1 个答案:

答案 0 :(得分:2)

DelayedInit怎么样?

import scala.util.control.Breaks._

trait BreakInit extends DelayedInit {
  def delayedInit(body: => Unit) {
    breakable {body}
  }
}

class MyClass extends BreakInit {
  println("Hello World")
  break()
  println("Error - should not be reachable")
}

val a = new MyClass

在这种情况下,我们创建了一个继承自BreakInit的特征DelayedInit,它会覆盖delayedInit方法以调用breakable块中的构造函数。然后将MyClass的构造函数汇总到一个函数中,并传递给delayedInit方法。正如@ som-snytt指出的那样,DelayedInit魔法只影响类构造函数,而不影响特征构造函数。

但是,在使用DelayedInit时,我建议您注意一下。它涉及一些相当深度的编译器魔法,魔法总是带来价格。就个人而言,我倾向于更喜欢你原来的方法,因为涉及的魔法较少。