2013-08-04 3 views
1

지연 시간을 사용하여 오버라이드 된 멤버 값을 수퍼 클래스 생성자에 전파하는 방법에 대해 this explanation이 발견되었습니다. 불행히도,이 기사는 왜 이것이 작동하는지 설명하지 않습니다.멤버 및 지연 시간 무시

non-lazy 값을 두 번 할당 할 수 없으므로 변수를 다른 값으로 잠그지 않으려면 수퍼 클래스 생성자의 값 할당을 건너 뛰야하므로 슈퍼 생성자에서 값을 사용할 수 없다는 것을 알고 있습니다. 그러나 슈퍼 생성자에서 실행되는 문, 즉 새 게으른 값이 asigned되기 전에 println 문은이 새로운 값에 대해 이미 알고 있습니까? 실행 명령에 대해 혼란 스럽습니까? 또는 println 어떻게 든 개체가 생성 된 후에 인수를 평가하는 것입니까?

답변

4

아주 간단합니다. 모든 필드와 게으른 필드는 getter 메소드라는 점에 유의해야합니다.

val getter는 private[this] 필드의 값을 반환합니다. private[this] 필드 할당은 기본 생성자에 있습니다

class Test { 
    private[this] val _field: Int = _ 
    def field = _field 

    { // constructor 
    _field = 1 
    } 
} 

그래서 전에 생성자 field 반환 기본값 :

class Test { 
    val field = 1 
} 

이 같은 것을 의미한다.

lazy val 이중 체크 잠금을 사용하여 코드 블록을 평가하고 반환 결과를보다 :

그래서 lazy val는 생성자와 아무 상관이있다, 당신은 동일한 결과를 얻을 수 있습니다 :

class Test { 
    lazy val field = 1 
} 

이 같은 의미 전후 생성자.

scalac -Xprint:mixin test.scala을 사용하여 확인할 수 있습니다.

+0

이렇게하면 어떻게 든 더 명확 해집니다. 그러나 getter가 서브 컨스트럭터의 실제 값으로 설정되기 전에 필드의 값에 액세스하는 방법은 여전히 ​​궁금합니다. JVM이 새 값이 설정된 명령문에 도달하기 전에 println 코드 행을 실행해야합니다. 이것이 어떻게 가능한지? println은 getter를 해결할 필요가 없으므로 실행시 기본 값에 액세스 할 필요가 있습니까? –

+0

@ printw 어떤 println을 원하십니까? – senia

+0

@raphw :'Use lazy vals.' 예제에서'println'은'x1'과'x2'를 호출합니다. 'x1'은'B'에 정의되어 있으며 생성자에는 아무 것도 없습니다. 'val'과'lazy val'이 아니라'def'라고 정의 할 수 있습니다. 'x2'는'A'에 정의되어 있고'C'에 덮어 쓰여져 있습니다. 또한 생성자와 아무런 관련이 없습니다. 생성자에서 오버라이드되지 않는 메소드. 이 예제에서'val'과'lazy val'을 모두'def'로 대체하려고하면 결과는 같을 것입니다. – senia