在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
一样完全忽略调试版本。
答案 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()