[코틀린기초] 27. 지연 초기화

클래스에서는 기본적으로 선언하는 프로퍼티 자료형들은 null을 가질 수 없다.

하지만 객체의 정보가 나중에 나타나는 경우 나중에 초기화 할 수 있는 방법이 필요하다.

그런 경우에 lateinitlazy 키워드를 사용하여 지연 초기화를 한다.

lateinit을 사용한 지연 초기화

### lateinit의 제한

  class Person{
    lateinit var name: String // 늦은 초기화를 위한 선언
    
    fun test(){
      if(!::name.isInitialized){  // 프로퍼티 초기화 여부 판단
        println("not isInitialized")
      }
      else{
        println("initialized")
      }
    }
  }
  
  lateinit var person1 Person // 객체 생성의 지연 초기화
  
  fun main(){
    val kildong = Person()
    kildong.test()
    kildong.name = "Kildong"  // 이 시점에서 초기화됨
    kildong.test()
    
  }

## lazy를 이용한 지연 초기화

  class LazyTest{
    init{
      println("init block")
    }
    
    private val subject by lazy { // 늦은 초기화. subject가 접근되는 시점에 초기화된다.
      println("lazy initialized")
      "Kotlin Programming"  //  lazy 반환 값
    }
    
    fun flow(){
      println("not initialized")
      println("subject one: $subject")  // 이때 subject가 초기화 된다!!
      println("subject who: $subject")  //  이미 초기화 된 값을 사용한다.
    }
  }
  
  fun main(){
    val test = LazyTest()
    test.flow()
  }

### by lazy로 선언된 객체 지연 초기화

  class Person(val name: String, val age: Int)
  
  fun main(){
    var isPersonInstantiated: Boolean = false //  초기화 확인 용도
    
    val person:  Person by lazy{  // lazy를 사용한 person 객체의 지연 초기화
      isPersonInstantiated = true
      Person("Kim",23)  //  이 부분이 lazy객체로 반환됨.
    }
    
    val personDelegate = lazy { Person("Hong",40) } // 위임 변수를 사용한 초기화
  
    println("person.name = ${person.name}") //이 시점에서 초기화
    println("personDelegate.value.name = ${personDelegate.value.name}") // 이 시점에서 초기화
  }

### by lazy의 모드

  private val model by lazy(mode= LazyThreadSafetyMode.NONE){
    Injector.app().transactionModel() //  이 코드는 단일 스레드의 사용이 보장될 때
  }