코틀린 강좌 #28 변수의 고급 기술. 상수, lateinit, lazy

Kotlin/기본 문법 · 2020. 12. 24. 16:36

테크과학! DiMo

 

테크과학! DiMo

개발자가 얘기하는 생활 속 IT기술에 대한 과학! 여러분이 몰랐던, 혹은 정확히 알지 못했던 IT 테크놀러지를 파드립니다! 좋은 영상을 위한 채널 후원, 투네이션을 통해서 해주세요! 후원링크 htt

www.youtube.com

 

 

개발 환경: play.kotlinlang.org


val은 할당된 객체를 바꿀 수 없을 뿐이지 객체 내부의 속성을 변경할 수 없는 것은 아니다.

그런데, 절대 변경이 불가능한 것도 있다.

 

 

상수(Constant)

 

컴파일 시점에 결정되어 절대 바꿀 수 없는 값. 

 

const val CONST_A = 1234



상수로 선언될 수 있는 값은 기본 자료형만 가능하며(*String 자료형을 포함)


런타임에 생성될 수 있는 일반적인 다른 클래스의 객체들은 담을 수 없다.

class Sample { const val CONST_A = 1234} (불가능) // 클래스의 속성으로 사용 할 수 없다 
fun sample {const val CONST_A = 1234 } (불가능) // 지역 변수로 사용 할 수 없다. 



반드시 companion object 안에 선언하여 객체의 생성과 관계없이 클래스와 관계된(Sample.CONST_A) 고

정적인 값으로만 사용하게 된다.

class Sample { 
	companion object { 
            const val CONST_A = 1234 
        } 
} 



상수의 이름을 만들 때는 의례적으로 대문자와 언더바(_)만 사용한 표기법을 사용하여 이를 통해 변수가 아

 

닌 상수라는 점을 알림

 

 

fun main() {
    val foodCourt = FoodCourt()
    
    foodCourt.searchPrice(FoodCourt.FOOD_CREAM_PASTA)
    foodCourt.searchPrice(FoodCourt.FOOD_STEAK)
    foodCourt.searchPrice(FoodCourt.FOOD_PIZZA)
}

class FoodCourt {
    fun searchPrice(foodName: String) {
        val price = when(foodName) {
            FOOD_CREAM_PASTA -> 13000
            FOOD_STEAK -> 25000
            FOOD_PIZZA -> 15000
            else -> 0
        }
        println("${foodName}의 가격은 ${price}원 입니다")
    }
    
    companion object {
        const val FOOD_CREAM_PASTA = "크림파스타"
        const val FOOD_STEAK = "스테이크"
        const val FOOD_PIZZA = "피자"
    }
}

Output:
크림파스타의 가격은 13000원 입니다
스테이크의 가격은 25000원 입니다
피자의 가격은 15000원 입니다

 

 

변수를 사용하지 않고 상수를 별도로 사용하는 이유

 


변수의 경우 런타임시 객체를 생성하는데 시간이 더 소요되어 성능의 하락이 있기 때문.


따라서 늘 고정적으로 사용할 값은 상수를 통해 객체의 생성 없이 메모리에 값을 고정하여 사용함으로써 성능을 향상 시

 

킬 수 있다.

 

 

 

늦은 초기화

 


코틀린에서는 변수를 선언할 때 객체를 바로 할당하지 않는 경우에는 기본적으로 컴파일이 불가능하다.


경우에 따라서 변수에 객체를 할당하는 것을 선언과 동시에 할 수 없을 때도 있다. 

 

lateinit var a: Int

 

이럴 때는 var 앞에 lateinit을 사용하여 일단 변수만 선언하고 초기값의 할당은 나중에 할 수 있도록 하는 키워드.

 

lateinit var 변수의 제한사항

 

 

초기값 할당 전까지 변수를 사용할 수 없음(에러 발생)


기본 자료형에는 사용할 수 없음(*String 클래스에서는 사용 가능)

 

또한 lateinit 변수의 '초기화'를 하였는지 여부를 확인할 때는 ::a.isInitialized 값을 확인해보면 초기화가 되었는지 확인하

 

여 사용할 수 있으므로 오류를 막을 수 있다.

 

 

fun main() {
    val a = LateInitSample()
    
    println(a.getLateInitText())
    a.text = "새로 할당한 값"
    println(a.getLateInitText())
}

class LateInitSample {
    lateinit var text: String
    fun getLateInitText(): String {
        if (::text.isInitialized) {
            return text
        } else {
            return "기본값"
        }
    }
}

Output:
기본값
새로 할당한 값

 

 

lazy delegate properties (지연 대리자 속성)


변수를 사용하는 시점까지 초기화를 자동으로 늦춰준다.


val a: Int by lazy{7}


lateinit과 달리 val 변수에 by라는 키워드를 사용하여 lazy라는 람다 함수 형태의 초기화 함수를 사용

코드에서는 선언 시 즉시 객체를 생성 및 할당하여 변수를 초기화하는 형태를 갖고 있지만 실제 실행 시에는 val 변수를

 

사용하는 시점에 초기화를 진행함으로써 코드의 실행시간을 최적화할 수 있는 코드.

 



참고로 람다 함수로 초기화가 진행되므로 함수 안에 여러 개의 구문이 들어갈 수 있다. 맨 마지막 구문의 결과가 변수

 

에 할당된다.

 

 

fun main() {
    val number: Int by lazy {
        println("초기화를 합니다")
        7
    }
    
    println("코드를 시작합니다")
    println(number)
    println(number)
}

Output:
코드를 시작합니다
초기화를 합니다
7
7