Scala - 使用App trait进行多重继承

时间:2017-01-04 18:32:48

标签: scala multiple-inheritance

考虑两个特征,TestTrait1和TestTrait,并假设NewObject扩展了两个特征。 我们的想法是在TestTrait中使用TestTrait1中的变量。以下代码完美无缺。

scala> trait TestTrait1 {
 | val arguments1: Array[String] = Array("1","2")
 | }

defined trait TestTrait1

scala> trait TestTrait {
 | val arguments: Array[String]
 | val len = arguments.length
 | }

defined trait TestTrait

scala> object NewObject extends TestTrait1 with TestTrait {
 |  lazy val arguments = arguments1
 | }

defined object NewObject

scala> NewObject
res30: NewObject.type = NewObject$@7c013560

现在用App替换TestTrait1。由于参数设置为延迟评估,我将假设即使在DelayedInit的情况下,下面的代码也可以工作。

scala> object NewObject extends App with TestTrait {
 | lazy val arguments = args
 | }

但事实并非如此。这背后的原因是什么?

scala> NewObject
java.lang.NullPointerException
at TestTrait$class.$init$(<console>:12)
... 35 elided

如果是这种情况,在这里使用类似于TestTrait的另一个特征中使用args的解决方案是什么?

1 个答案:

答案 0 :(得分:2)

trait TestTrait1 {
  val arguments1: Array[String] = Array("1","2")
}

trait TestTrait {
  val arguments: Array[String]
  val len = arguments.length
}

如果你看到差异,那么TestTrait会有一个成员len,它会急切地被初始化。但是argsdef App内部null,其默认值恰好为len。如果您将lazy val更改为defscala> :paste // Entering paste mode (ctrl-D to finish) trait TestTrait { def arguments: Array[String] lazy val len = arguments.length } object NewObject extends App with TestTrait { override lazy val arguments = super.args // Added `override` and `super` just for clarity. } // Exiting paste mode, now interpreting. defined trait TestTrait defined object NewObject scala> NewObject res0: NewObject.type = NewObject$@5ace1ed4 scala> NewObject.arguments res1: Array[String] = null ,则NPE不会爆炸。

让我们在快速REPL会话中尝试这个:

len

如果您想重现此问题,可以拨打scala> NewObject.len java.lang.NullPointerException at TestTrait$class.len(<console>:12) at NewObject$.len$lzycompute(<console>:15) at NewObject$.len(<console>:15) ... 33 elided ,如下所示:

len

因此,对于您的问题的答案是,如果要调用lazy val的实例,则需要def NewObjectclass。我建议将NewObject设为traitlen,因为您不希望使用NPE爆炸的不安全/急切初始化的#!/bin/bash ds() { date --date="$1 weeks ago" +%Y-%m-%d } BRANCH=master # your branch here echo "Week,Lines Changed" for week in {80..1} do # git log outputs lines like: # 11 10 path/to/your/file.java # => add first two columns with awk lines=$(git --no-pager log --after=$(ds $week) --before=$(ds $(($week - 1))) --format=format: --numstat $BRANCH | awk '{s+=$1; s+=$2} END {print s}') echo "$(ds $week),$lines" done 成员。