본문 바로가기
언어/Kotlin

[Kotlin 문법 종합] - 지연 초기화 (@@0313 추가중~)

by 젼젼39 2024. 3. 6.

 

1. 지연 초기화

    : 클래스 설계 시 초기의 값 설정하기 애매할 때, 나중에 대입

    (+) 메모리의 효율적인 사용

 

1) 변수 --> lateinit

    - isInitialized --> 변수 사용 전, 초기화되었는지 확인해 true/false 반환 ( !::name.isInitialized)
    - 값이 아니라 참조형태로 사용해야 하기에 this::~ 또는 :: 붙임

    // var에만 사용 가능, 프로퍼티에 대한 게터, 세터를 사용할 수 없음(초기화된 뒤에는 수정 가능하긴 한 듯)

fun main(){
    var s1 = Student()
    s1.name = "참새" 		//이 때 초기화됨
    s1.displayInfo()

    s1.age = 10
    s1.displayInfo()
}

class Student {
    lateinit var name:String 		// 여기
    var age:Int = 0

    fun displayInfo() {
        if(this::name.isInitialized) { 			//여기
            println("이름은: ${name} 입니다.")
            println("나이는: ${age} 입니다.")
        } else {
            println("name변수를 초기화해주세요.")
    	}
    }
}

 

2) 상수 --> lazy

    - 사용 시점에 값을 대입하고 초기화됨         

fun main(){
    var s1 = Student()
    s1.name = "참새"
    s1.displayInfo() 		//이 때 한번 초기화됨, address 초기화 출력된 후 주소는 : ~ 출력됨

    s1.age = 10
    s1.displayInfo() 		//이 땐 address 초기화 출력되지 않음
}

class Student {
    lateinit var name:String
    var age:Int = 0
    val address: String by lazy { 		// <-- 여기
        println("address 초기화")
        "seoul" 						//초기화값 넣어줌
    }

    fun displayInfo() {
        println("이름은: ${name} 입니다.")
        println("나이는: ${age} 입니다.")
        println("주소는: ${address} 입니다.")
    }
}
class LazyTest{
    init{
        println("init block")
    }
    val subject by lazy{
        println("lazy initialized")
        "Kotlin Programming" 		//반환값
    }
    fun flow(){
        println("Not initialized")
        println("s1 : $subject") 	//최초 초기화 시점
        println("s2 : $subject") 	//초기화된 값 사용하기
    }
}

fun main(){
    val test = LazyTest()
    test.flow()    
}
class Person(val name: String, val age : Int)

fun main(){
    var isPersonInstantiated: Boolean = false
    
    val person : Person by lazy{
        isPersonInstantiated = true
        Person("Choi", 22)
    }
    
    val personDelegate = lazy { Person("Lee", 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 할당 -> 변수에 위임된 lazy 객체를 나타내는 것.
                이 변수의 lazy를 한 단계 더 거쳐 객체의 멤버인 value.name과 같은 형태로 접근해야 함

 

    *by를 이용한 위임

1. 클래스의 위임

interface Animal{
    fun eat(){...}
}

class Cat : Animal{ } 		//인터페이스
val cat = Cat() 		//Cat, 인터페이스 구현

class Robot : Animal by cat

Animal의 정의된 Cat의 모든 멤버를 Robot에 위임
Cat은 Animal의 private 멤버로 Robot 클래스 안에 저장됨
Cat에서 구현된 모든 Animal의 메소드는 정적 메소드로 생성됨
-> Robot 클래스에서 Animal을 명시적으로 참조하지 않고도 eat()을 바로 호출할 수 있음

@@275~