可以有条件地省略子类方法吗?

时间:2014-05-04 04:22:34

标签: scala

在Scala中,我希望根据命令行优先级有条件地省略子类方法(并恢复到基类实现)。例如,假设我有以下代码:

// File: mini.scala

import scala.annotation._, elidable._

trait FooBase {

  def bar(msg: String) = println("FooBase: " + msg)
}

object Foo extends FooBase {

  @elidable(INFO)
  override def bar(msg: String) = println("Foo: " + msg)
}

object App {

  def main(args: Array[String]) {
    println("before")
    Foo.bar("message")
    println("after")
  }
}

如果我编译:

scalac -Xelide-below MINIMUM mini.scala

运行它,我看到(正如预期的那样):

before
Foo: message
after

现在如果我用:

编译
scalac -Xelide-below MAXIMUM mini.scala

然后,我希望看到:

before
FooBase: message
after

但我实际上看到了:

before
after

因此,基类似乎也没有被消除(如希望的那样),而不仅仅是子类方法。

任何解释都表示赞赏。


根据@ som-snytt的回应,似乎达到我之后效果的最佳方式是:

trait DebugBase {
    def on = false
}

object Debug extends DebugBase {
   @elidable(INFO)
   override def on = true
}

object Foo {
  def bar(msg: String) = if (Debug.on) println("Foo (Debug): " + msg) else println("Foo: " + msg)
}

但是,仍然会对Debug.on的状态进行运行时检查,而不是像在C / C ++中使用#ifdef一样完全忽略调试版本。

1 个答案:

答案 0 :(得分:1)

这是一个很好的。我曾经看过机制,但我不确定用例。

答案是评论:

/** Called if a tree's symbol is elidable.  If it's a DefDef,
 *  replace only the body/rhs with 0/false/()/null; otherwise replace
 *  the whole tree with it.
 */

因此,在删除Foo.bar时,您不会删除方法定义。您只需将其转换为def bar = ()并将其调用为单位值()

您可以有效地省略模板方法:

scala> class X { def f() = { if (g() < 1) println("default") } ; def g() = 1 }
defined class X

scala> :se -Xelide-below 200

scala> class Y extends X { @elidable(100) override def g() = 2 }
defined class Y

scala> new Y().f()
default

scala> :se -Xelide-below 5

scala> class Y extends X { @elidable(100) override def g() = 2 }
defined class Y

scala> new Y().f()