복붙노트

[SCALA] 스칼라 - 발스의 초기화 순서

SCALA

스칼라 - 발스의 초기화 순서

나는이 코드 조각이 그 파일에서로드 속성 :

class Config {
  val properties: Properties = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
  }

  val forumId = properties.get("forum_id")
}

이것은 잘 작동하는 것 같군.

나는 이런 식으로, 다른 발에 속성의 초기화를 이동 loadedProperties을 시도했다 :

class Config {
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")

  private val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p 
   }

}

그러나 그것은 작동하지 않습니다! (속성은 () "forum_id"properties.get에 널 (null)입니다).

왜 그 것입니까? 속성에 의해 참조 될 때 loadedProps 평가되지 않는 이유는 무엇입니까?

둘째, 이것은 비 단순 처리에 필요한 변수를 초기화 할 수있는 좋은 방법이다? 자바에서 나는 그들에게 마지막 필드를 선언하는 것이고, 생성자에서 초기화 관련 작업을 수행합니다.

스칼라에서이 시나리오에 대한 패턴이 있습니까?

감사합니다!

해결법

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

    1.발스는 특성 때문에 loadedProps 전에 초기화지고,이 선언되고있는 순서로 (물론, 정확하게, 비 게으른 놈들이다)에 초기화됩니다. 초기화하기 propertiesis 때 또는 다른 말로, loadedProps은 여전히 ​​null입니다. 여기에 가장 간단한 해결책은 등록 전에 loadedProps을 정의하는 것입니다 :

    발스는 특성 때문에 loadedProps 전에 초기화지고,이 선언되고있는 순서로 (물론, 정확하게, 비 게으른 놈들이다)에 초기화됩니다. 초기화하기 propertiesis 때 또는 다른 말로, loadedProps은 여전히 ​​null입니다. 여기에 가장 간단한 해결책은 등록 전에 loadedProps을 정의하는 것입니다 :

    class Config {
      private val loadedProps = {
        val p = new Properties()
        p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
        p 
      }
      val properties: Properties = loadedProps
      val forumId = properties.get("forum_id")
    }
    

    당신은 또한 최초의 액세스에 초기화됩니다 것을 의미 loadedProps 게으른을 만들 수 있습니다 :

    class Config {
      val properties: Properties = loadedProps
      val forumId = properties.get("forum_id")
    
      private lazy val loadedProps = {
        val p = new Properties()
        p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
        p 
      }
    }
    

    게으른 발을 사용하면 단순히 코드를 아프게하지 것이다 발스의 선언 순서 변경과 같은 코드가 리팩토링에 더 강력하다는 장점이있다.

    (@NIA에 의해 제안)가 한 번만 어쨌든 사용되는 또한이 특정 선두로부터, 당신은 단지 데프으로 loadedProps을 해제 할 수 있습니다.

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

    2.나는 loadedProps 단순히 단순히 데프와 함께 발을 바꾸어 기능으로 설정할 수 있습니다 여기에 생각한다 :

    나는 loadedProps 단순히 단순히 데프와 함께 발을 바꾸어 기능으로 설정할 수 있습니다 여기에 생각한다 :

    private def loadedProps = {
      // Tons of code
    }
    

    이 경우 당신은 당신이 그것을 호출 할 때 호출 될 것을 확신합니다.

    하지만 확실하지가이 경우에 대한 패턴이다.

  3. ==============================

    3.좀 더 설명에 그냥 추가 :

    좀 더 설명에 그냥 추가 :

    귀하의 속성 필드는 여기 loadedProps 필드보다 먼저 초기화합니다. 당신이 그것을 얻을 이유 - 널 (null) 초기화하기 전에 필드의 값입니다. 모든 벌금 (- 여기에는 초기화 메소드의 코드가 여러 번 호출 할 수 있으므로), 그래서 데프 경우는, 단지 대신 일부 필드를 액세스하는 메소드 호출이다. , http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html를 참조하십시오. 당신은 DEF 사용하거나 게으른 발은 그것을 해결하기 위해

    왜 데프 그렇게 다른가요? 한 번만 (첫 번째와 한 통화 만 실제로 fileld의 초기화하므로) - 데프 여러 번 호출 할 수 있기 때문에, 그러나 발 그.

    당신이 그것을 호출 할 때 그것은 또한 도움이 될 수 있도록 게으른 발 만 초기화 할 수 있습니다.

    무엇의 또 다른 간단한 예에 무슨 :

    scala> class A {val a = b; val b = 5}
    <console>:7: warning: Reference to uninitialized value b
           class A {val a = b; val b = 5}
                            ^
    defined class A
    
    scala> (new A).a
    res2: Int = 0 //null
    

    보다 일반적으로 이야기 이론적 스칼라 (필드가 다른 필드가 필요)의 필드 사이의 종속성 그래프 analize 수 있고, 최종 노드로부터 초기화를 시작한다. 그러나 실제로 모든 모듈은 별도로 컴파일하고 그냥 순차적으로 초기화를 그래서 컴파일러는 심지어 (이 자바를 호출 스칼라를 호출에도 자바, 수 있습니다) 그 종속성을 알고하지 않을 수 있습니다.

    그래서, 그 때문에, 심지어는 간단한 루프를 감지 할 수 있습니다 :

    scala> class A {val a: Int = b; val b: Int = a}
    <console>:7: warning: Reference to uninitialized value b
           class A {val a: Int = b; val b: Int = a}
                                 ^
    defined class A
    
    scala> (new A).a
    res4: Int = 0
    
    scala> class A {lazy val a: Int = b; lazy val b: Int = a}
    defined class A
    
    scala> (new A).a
    java.lang.StackOverflowError
    

    사실, 이러한 루프는 (하나 개의 모듈 내부) 이론적으로 별도의 빌드에서 검출 될 수 있지만, 그것은 꽤 분명 많이 도움이되지 않습니다.

  4. from https://stackoverflow.com/questions/14568049/scala-initialization-order-of-vals by cc-by-sa and MIT license