이동식 저장소

[Kotlin] Inline class 본문

Primary/Kotlin

[Kotlin] Inline class

해스끼 2022. 5. 4. 14:41

참고: 이 글은 Kotlin - Inline classes 공식 문서를 번역한 글입니다.

 

Inline classes | Kotlin

 

kotlinlang.org


비즈니스 로직에서 primitive 타입을 감싸야 하는 경우가 가끔 생긴다. 예를 들어 Card의 고유 아이디를 val id: Long으로 나타낼 수도 있지만, CardId 클래스를 이용하여 표현하면 의미를 더 명확히 드러낼 수 있다.

 

겨우 아이디 하나 때문에 그렇게까지 해야 하나 싶기도 하지만, 멤버 변수의 값에 제한이 있는 경우 inline class를 유용하게 사용할 수 있다. 예를 들어 month라는 변수는 1부터 12까지의 값만을 가질 수 있으므로 13 이상의 값이 주어지면 값을 할당하지 않도록 코드를 짤 수도 있다.

 

이런 경우 Kotlin의 inline class를 사용해볼 수 있다. inine class는 값을 저장하는 용도로만 사용해야 한다.

inline class

다음과 같이 inline class를 선언할 수 있다.

@JvmInline
value class Password(private val s: String)

자바 바이트코드로 컴파일하는 경우 @JvmInline 어노테이션을 추가해야 하며, class 앞에 inline이 아닌 value를 쓴다는 점에 주의하자. inline은 deprecate되었다.

 

Inline class는 생성자에서 초기화되는 변수 하나만을 가져야 한다. 실제 런타임에서는 객체가 생성되지 않고, 감싸진 변수가 직접 할당된다.

val password = Password("Some password")

예를 들어, 위의 코드는 Password 객체를 만들지 않는다. 대신 문자열 자체가 할당되고, 런타임에서 password 변수에는 자바 문자열이 할당된다. 이제 inline이라는 말을 이해할 수 있을까?

멤버 변수? 멤버 함수?

Inline class는 init 블럭, 멤버 변수, 멤버 함수를 가질 수 있다. lateinit이나 위임된 변수는 선언할 수 없다.

@JvmInline
value class Name(val s: String) {
    init {
        require(s.length > 0) { }
    }

    val length: Int
        get() = s.length

    fun greet() {
        println("Hello, $s")
    }
}

이때 멤버 변수와 함수는 내부적으로 마치 확장 함수처럼 호출된다. 

 

위의 코드에서처럼 init 블럭 안에서 값을 검사하고, 잘못된 값이 들어오는 경우를 걸러낼 수 있다. 그 다음엔 exception을 던지던가, 에러를 출력하던가 원하는 대로 하면 된다.

상속

Inline class는 인터페이스를 상속받을 수 있다. 하지만 클래스를 상속받을 수는 없으며, 자기 자신이 부모 클래스가 될 수도 없다.

Comments