14. 프로퍼티와 지연 초기화 (lateinit, lazy)
코틀린은 필드(Field) 대신 프로퍼티(Property)를 사용합니다. 변수처럼 보이지만, 내부적으로는 get()과 set() 메서드가 암묵적으로 호출됩니다. 커스텀 게터를 만들어 값을 동적으로 계산할 수도 있습니다.
또한 안드로이드 환경이나 의존성 주입 시 "변수를 나중에 초기화해야 할 때" 널러블(?)을 피하기 위해 lateinit(나중에 초기화)이나 lazy(처음 불릴 때 생성)를 유용하게 활용합니다.
class Rectangle(var width: Int, var height: Int) {
// 1. 커스텀 Getter (변수처럼 접근하지만 사실은 내부적으로 계산 함수가 실행됨)
val isSquare: Boolean
get() = (width == height)
val area: Int
get() = width * height
}
class Profile {
// 2. lateinit: var 에만 사용. 나중에 초기화할 것임을 약속함. (null 방지)
lateinit var nickname: String
// 3. lazy: val 에만 사용. 해당 변수가 "처음" 불릴 때 중괄호 안의 코드가 실행됨.
val heavyData: String by lazy {
println("=> 복잡하고 오래 걸리는 데이터 로딩 중...")
"거대한 용량의 데이터셋"
}
}
fun main() {
val rect = Rectangle(10, 10)
println("정사각형인가? " + rect.isSquare) // true
println("면적: " + rect.area) // 100
val p = Profile()
// println(p.nickname) // 초기화 전 호출 시 UninitializedPropertyAccessException 에러!
p.nickname = "코틀린러버"
println("설정된 닉네임: " + p.nickname)
println("lazy 데이터는 아직 로딩 안 됨.")
println("1차 호출: " + p.heavyData) // 이 때 로딩 로그가 찍힘
println("2차 호출: " + p.heavyData) // 이미 로딩된 값을 반환 (로그 안 찍힘)
}