App노자

[Kotlin] 지연 초기화 본문

Android/Kotlin

[Kotlin] 지연 초기화

앱의노예 2023. 8. 5. 17:46

1. 지연 초기화란?


코틀린은 변수 선언 시 초기화를 할 것을 권고하며 변수 선언 시 초기화를 하지 않거나

nullable 타입으로 만들어주지 않으면 컴파일 에러가 발생한다.

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

생성자에서 초기화하거나 매개변수로부터 값을 초기화하는 것이 규칙이다

하지만 객체의 정보가 나중에 나타나는 경우 객체 생성과 동시에 초기화하기 힘들어지는데

이때 사용하는 게 지연초기화이다 

지연초기화는 lateinit과 lazy키워드를 통해 사용할 수 있다

2. lateinit


class Person {
    lateinit var name: String

    fun test() {
        if(!::name.isInitialized) { // 프로퍼티의 초기화 여부 판단
            println("not initialized")
        } else {
            println("initialized")
        }
    }
}

fun main() {
    val choi = Person()
    choi.test()
    choi.name = "choi" // 이 시점에서 초기화가 된다. (지연초기화)
    choi.test()
    println("name = ${choi.name}")
}

클래스를 선언할 때 프로퍼티 선언은 null을 허용하지 않는다 지연 초기화 lateinit 키워드를 사용하면 프로퍼티에 값이 바로 할당되지 않아도 컴파일러에서 허용하게 된다 단 실행할 때까지도 값이 비어 있는 상태면 오류가 발생한다

lateinit에는 var로 선언된 프로퍼티에만 가능하다와 프로퍼티에 대한 게터와 세터를 사용할 수 없다는 제한이 있다

 

https://kotlinlang.org/docs/properties.html#checking-whether-a-lateinit-var-is-initialized

 

Properties | Kotlin

 

kotlinlang.org

3. lazy


class LazyTest {
    init {
        println("init block") // (2)
    }

    val subject by lazy {
        println("lazy initialized") // (6)
        "Kotlin Programming" // (7) lazy 반환값
    }
    fun flow() {
        println("not initialized") // (4)
        println("subject one: $subject") // (5) 최초 초기화 시점!
        println("subject two: $subject") // (8) 이미 초기화된 값 사용
    }
}

fun main() {
    val test = LazyTest() // (1)
    test.flow() // (3)
}

lazy는 람다식으로 구성되어 lazy 인스턴스 반환값을 가지는 함수이며

val로 선언한 객체나 프로퍼티를 나중에 초기화할 때 사용한다

lazy는 아래의 3가지 특징을 가지고 있다

- 호출 시점에 by lazy 정의에 의해 블록 부분의 초기화를 진행한다

- 불변의 변수 선언인 val에서만 사용 가능하다

- val이므로 값을 다시 변경할 수 없다

class Person(val name: String, val age: Int)

fun main() {
    var isPersonInstantiated: Boolean = false

    val person : Person by lazy {
        isPersonInstantiated = true
        Person("Kim", 23)
    }
    val personDelegate = lazy { Person("Hong", 40) }

    println("person Init: $isPersonInstantiated")
    println("personDelegate Init: ${personDelegate.isInitialized()}")

    println("person.name = ${person.name}")  // 이 시점에서 초기화
    println("personDelegate.value.name = ${personDelegate.value.name}")  // 이 시점에서 초기화

    println("person Init: $isPersonInstantiated")
    println("personDelegate Init: ${personDelegate.isInitialized()}")
}

객체에 대한 lazy 지연 초기화이다

초기화되는 시점은 객체의 프로퍼티나 메서드가 접근되는 시점에서 초기화가 된다

by lazy와 lazy 할당의 차이점은 by lazy는 객체의 위임을 나타내고 lazy는 변수에 위임된 Lazy 객체 자체를 나타내므로

value를 한 단계 더 거쳐 객체의 멤버인 value.name과 같은 형태로 접근해야 한다는 것이다

 

https://kotlinlang.org/docs/delegated-properties.html#lazy-properties

 

Delegated properties | Kotlin

 

kotlinlang.org

 

 

 

 

 

 

'Android > Kotlin' 카테고리의 다른 글

[Kotlin] 코틀린 표준 라이브러리  (0) 2023.08.09
[Kotlin] by 키워드  (0) 2023.08.06
[Kotlin] 컬렉션의 확장 함수  (0) 2023.08.04
[Kotlin] sequence (시퀀스)  (0) 2023.08.03
[Kotlin] Set과 Map  (0) 2023.07.30