1. 인라인 클래스

2. 핵심 개념

// 인라인 클래스 선언
@JvmInline
value class UserId(val id: Long)

@JvmInline
value class EmailAddress(val email: String) {
    fun isValid(): Boolean = email.contains("@")
}

// 사용 예
fun main() {
    val userId = UserId(42L)
    val emailAddress = EmailAddress("[email protected]")
}

// 컴파일 후
fun main {
    val userId: Long = 42L // 내부 값인 Long 타입으로 대체됨
    val emailAddress: String = "[email protected]" // 내부 값인 String 타입으로 대체됨
}

3. 언제 사용하면 좋은지?

  1. 측정 단위 표현

    @JvmInline
    value class Meters(val value: Double)
    
    @JvmInline
    value class Kilometers(val value: Double)
    
  2. type-safe한 ID 만들기

    @JvmInline
    value class UserId(val value: Long)
    
    @JvmInline
    value class OrderId(val value: Long)
    
  3. 도메인 특화 타입 정의

    @JvmInline
    value class EmailAddress(val value: String) {
        init {
            require(value.contains("@")) { "Invalid email format" }
        }
    }
    
  4. enum을 대체하면서 더 유연한 값 표현

    @JvmInline
    value class Currency(val code: String)
    
    val usd = Currency("USD")
    

4. 주의사항

  1. 인터페이스

    // 인터페이스로 ID 타입 정의
    interface TimeUnit { val millis: Long }
    
    @JvmInline
    value class Minutes(val minutes: Long): TimeUnit {
        override val millis: Long
            get() = minutes * 60 * 1000
    }
    
    @JvmInline
    value class Millis(val milliseconds: Long): TimeUnit {
        override val millis: Long
            get() = milliseconds
    }
    
    fun setUpTimer(time: TimeUnit) {
        val millis = time.millis
        // ...
    }
    
    fun main() {
        setUpTimer(Minutes(123))
        setUpTimer(Millis(456789))
    }