우리는 코드를 쓸 때 하나의 value 값만을 가지고 있는 클래스를 좀 더 도메인을 다루듯 사용하고 싶어 클래스로 래핑하고 싶은 경우가 있다. 하지만 이러한 방식은 heap allocation 으로 인해 런타임 오버헤드가 생길 수 있다. 특히 primitive 타입은 최적화가 잘 되어있기 때문에 이를 래핑하는 클래스를 만드는 것은 더욱 큰 오버헤드를 가져올 수 있다.
이러한 문제를 해결하기 위해서 코틀린은 inline class 라는 것을 제공한다.
@JvmInline
value class Password(private val s: String)
인라인 클래스는 항상 하나의 프로퍼티만 가지고 있어야하며, 주생성자로 초기화되어야 한다. 런타임에는 이 인스턴스가 single property로 동작한다. 이게 어떤 말이냐면..
val password = Password("jahni123")
위와 같은 코드를 쓰게되면 런타임에는 Password 클래스가 인스턴스화 되는 것이 아니고 jahni123 이라는 단순 스트링으로 처리된다.
이러한 value class를 사용하면 같은 데이터 타입을 사용하는 여러 값들 사이에서 혼동을 방지할 수 있다. 예를 들어 다음과 같이 쓸 수 있다.
@JvmInline
value class UserId(val id: String)
@JvmInline
value class ProductId(val id: String)
fun findUser(userId: UserId) { /*...*/ }
fun findProduct(productId: ProductId) { /*...*/ }
findUser(UserId("123")) // OK
findProduct(ProductId("123")) // OK
// findUser(ProductId("123")) // ERROR: 타입이 다름
value class는 내부적으로 항상 불변이다. 불변이 주는 장점을 다 취할 수 있는 것이다.
@JvmInline
value class Age(val value: Int)
val age = Age(25)
// age.value = 30 // 컴파일 오류: 값을 변경할 수 없음