2017-01-04 3 views
4

TestTrait1과 TestTrait의 두 가지 특성을 고려하여 NewObject가 두 가지를 모두 확장한다고 가정합니다. TestTrait에서 TestTrait1의 변수를 사용하는 것이 좋습니다. 아래 코드는 완벽하게 작동합니다.스칼라 - App trait을 사용한 다중 상속

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 = [email protected]3560 

이제 TestTrait1을 App으로 대체하십시오. 인수가 지연 평가를 위해 설정되었으므로 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를 사용하는 솔루션은 무엇입니까? 당신은 차이를 볼 경우

답변

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입니다. lenlazy val 또는 def으로 변경하면 NPE가 폭발하지 않습니다. 당신이 문제를 재현하려면

scala> :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 = [email protected] 

scala> NewObject.arguments 
res1: Array[String] = null 

당신이 아래 len를 호출 할 수 있습니다 :

의가 빠른 REPL 세션에서이 작업을 해보자

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 

그래서, 질문에 대한 대답은 당신입니다 NewObject 인스턴스를 호출하려면 lenlazy val 또는 def으로 만들어야합니다. NewObject를 class 또는 trait으로 만들 것을 권장합니다. 안전하지 않거나 열심히 초기화 한 len 멤버가 NPE로 폭발하는 것을 원하지 않기 때문입니다.

+1

동일한 예와 함께 설명해 주셔서 감사합니다. 설명은 완벽합니다. – rashmina