我怎样才能从特质中获取args?

时间:2015-03-25 17:40:49

标签: scala

以下代码:

trait TestMainArgs extends App {
  println(s"args are: $args") // I need to have a generic main in trait which refers to args...
}

object MyRealMainObj extends TestMainArgs {
  // I do not want to call the generic main from objects this would mean I would need to call them from every object which extendfs TestMainArgs
}

打印:

args are: null

以下内容:

trait TestMainArgs extends App {
}

object MyRealMainObj extends TestMainArgs {
  println(s"args are: $args")
}

打印:

args are: [Ljava.lang.String;@f82f98

那么如何从特征中访问args?

我想将"main"的逻辑只放在超级trait中,我不想要代码重复,比如从每个扩展应用程序超级主要的对象调用,有没有实现这一目标的方法?

2 个答案:

答案 0 :(得分:3)

答案在于查看Scala源代码中的DelayedInitApp。真正的宝石在于DelayedInit开头的doc评论:

Example:
 *  {{{
 *    trait Helper extends DelayedInit {
 *      def delayedInit(body: => Unit) = {
 *        println("dummy text, printed before initialization of C")
 *        body // evaluates the initialization code of C
 *      }
 *    }
 *
 *    class C extends Helper {
 *      println("this is the initialization code of C")
 *    }
 *
 *    object Test extends App {
 *      val c = new C
 *    }
 *  }}}
 *
 *  Should result in the following being printed:
 *  {{{
 *    dummy text, printed before initialization of C
 *    this is the initialization code of C
 *  }}}

所以,只需扩展DelayedInit,按照你在App中看到的警告(具体来说,不要覆盖扩展类中的args),你应该能够像App一样访问它们:

@deprecatedOverriding("main should not be overridden", "2.11.0")
def main(args: Array[String]) = {
  this._args = args
  //other stuff goes here as you like
}

但是,如果您这样做,请注意它已被弃用,就像它在那里所说的那样,因此您将面临在未来版本的Scala中丢失功能的风险。

答案 1 :(得分:3)

另一个不推荐使用的选项是覆盖main

trait TestMainArgs extends App {
  override def main(args: Array[String]) {
    println(s"args are: ${args(0)} from test")
    super.main(args)
  }
}

问题在于编译traits的方式,在主对象之前触发构造函数,这是设置args的地方。似乎没有不弃用的方法来做到这一点......