더북(TheBook)

lateinit 프로퍼티와 달리 lazy 프로퍼티는 불변 프로퍼티가 아니다. lazy 프로퍼티는 일단 초기화된 다음에는 변경되지 않는다.

// error: type 'Lazy<String>' has no method 'setValue(Chapter4, KProperty<*>, String)' and thus it cannot serve as a delegate for var (read-write property)
var text by lazy { "Hello" }

디폴트로 lazy 프로퍼티는 스레드 안전(thread-safe)하다. 즉, 다중 스레드 환경에서도 값을 한 스레드 안에서만 계산하기 때문에 lazy 프로퍼티에 접근하려는 모든 스레드는 궁극적으로 같은 값을 얻게 된다.

코틀린 1.1부터는 지역 변수에도 위임을 쓸 수 있게 됐다. 이 기능을 사용하면 함수 본문에서 지연 변수를 정의할 수 있다.

fun longComputation(): Int {...}

fun main(args: Array<String>) {
  val data by lazy { longComputation() } // lazy 지역 변수
  val name = args.firstOrNull() ?: return
  println("$name: $data") // name이 널이 아닐 때만 data에 접근할 수 있음
}

지금 현재 위임 프로퍼티에 대해서는 스마트 캐스트를 사용할 수 없다는 점에 유의하라. 위임은 구현이 다 다를 수 있기 때문에 커스텀 접근자로 정의된 프로퍼티처럼 다뤄진다. 그리고 이 말은 위임을 사용한 지역 변수의 경우에도 스마트 캐스트를 쓸 수 없다는 뜻이기도 하다.

fun main() {
  val data by lazy { readLine() }
  
  if (data != null) {
    // error: smart cast to 'String' is impossible, because 'data' is a property that has open or custom getter
    println("Length: ${data.length}")
  }
}

lazy 프로퍼티와 lazy 지역 변수는 다르지 않다. 현재로서는 이 둘의 값이 초기화된 다음에 실제로 값이 바뀌지 않더라도 스마트 캐스트를 적용할 수 없다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.