복붙노트

[SCALA] 앞으로의 참조 - 왜이 코드를 컴파일합니까?

SCALA

앞으로의 참조 - 왜이 코드를 컴파일합니까?

이 조각을 고려 :

 object A {
     val b = c
     val c = "foo"
 }
 println( A.b )   // prints "null"

큰 프로그램의 일환으로,이 런타임에 실패로 이어질 것입니다. 컴파일러는 명백하게 C 원래 NULL 값으로 남아 초기화되지 'C'그러나 'B'에서 'B'에서 전방 참조를 가능하게한다. 왜 이런 일이 허용된다? 이 기능에서 도움이 될 시나리오가 프로그래밍을하고 있습니까?

직선 순서와 동작 변화에 코드를 변경합니다 :

 val b = c
 val c = "foo"
 println( b )   // prints "foo"

왜 행동 다른 무엇입니까? 그리고 왜이도 작동합니까? 감사.

업데이트 1 :

내가 두 번째 예제를 실행하는 방법을 질문 내놓았다. 내가 설정을 조금 단순화하고 최신 스칼라 플러그인하게 IntelliJ IDEA 10.5.2 내부 스칼라 2.9.0.1을 사용하여 컴파일. 여기에 정확한 코드 내가이,이 환경에 어떤 컴파일 및 실행 벌금을 테스트하는 데 사용하고 새로 생성되고 그렇지 않으면 빈 프로젝트에 있습니다 :

 package test
 object Main { 
    def main( args: Array[String] ) {
       val b = c
       val c = "foo"
       println( b )   // prints "foo"
    }
 }

나는 'C'의 (이상) 선언을 참조 오전 (내가 발 B = C에서 'C'에 대한 참조 '를 통해 "클릭 할 때) 무엇의 가치를 들면, IDEA는 생각한다.

해결법

  1. ==============================

    1.클래스 또는 객체의 몸은 기본 생성자입니다. 생성자는 방법과 같은 순서로 실행되는 문장의 순서입니다 - 다른 작업을 수행하기 위해, 그것은 매우 다른 언어로 할 것이다. 나는 확신 당신이하고자하지 스칼라 순차적 이외의 순서에 따라 방법의 문을 실행 할 수있다.

    클래스 또는 객체의 몸은 기본 생성자입니다. 생성자는 방법과 같은 순서로 실행되는 문장의 순서입니다 - 다른 작업을 수행하기 위해, 그것은 매우 다른 언어로 할 것이다. 나는 확신 당신이하고자하지 스칼라 순차적 이외의 순서에 따라 방법의 문을 실행 할 수있다.

    문제는 여기에 클래스와 객체의 몸도 회원의 선언 있다는 것입니다, 이것은 당신의 혼란의 근원이다. 당신은 정확하게 그 인 것으로 발 선언을 참조 : 프로그래밍의 선언적 형태, 프롤로그 프로그램이나 XML 구성 파일처럼. 그러나 그들은 정말 두 가지 있습니다 :

    // This is the declarative part
    object A {
      val b
      val c
    }
    
    // This is the constructor part
    object A {
      b = c
      c = "foo"
    }
    

    문제의 또 다른 부분은 당신의 예는 아주 간단한 것입니다. 그것은 어떤 행동이 이해가 보인다되는 특별한 경우이다. 그러나 무언가를 같이 고려 :

    abstract class A {
      def c: String
    }
    
    class B extends A {
      val b = c
      override val c = "foo"
    }
    
    class C extends { override val c = "foobar" } with B
    
    val x = new C
    println(x.b)
    println(x.c)
    

    무슨 일이 기대합니까? 생성자 실행의 의미는 두 가지를 보장합니다 :

    산출:

    그것은 더 => https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html 두 번 "는 foobar"를 인쇄합니다

  2. ==============================

    2.이 때문에 스칼라의 오래된 버전입니다.

    이 때문에 스칼라의 오래된 버전입니다.

    스칼라 2.11.5으로는 경고와 함께 컴파일 또는 전혀 컴파일되지 않습니다 :

    C:\Users\Andriy\Projects\com\github\plokhotnyuk>scala
    Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_31).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> { object A { val b = c; val c = "foo" }; println(A.b) }
    <console>:9: warning: Reference to uninitialized value c
                  { object A { val b = c; val c = "foo" }; println(A.b) }
                                       ^
    null
    
    scala> { val b = c; val c = "foo"; println(A.b) }
    <console>:9: error: forward reference extends over definition of value b
                  { val b = c; val c = "foo"; println(A.b) }
                            ^
    
  3. from https://stackoverflow.com/questions/7762838/forward-references-why-does-this-code-compile by cc-by-sa and MIT license