이제 타입을 섞어 사용하면 컴파일러가 경고한다. 이는 여러분이 val weight: Weight와 val price: Price라고 타입을 지정하면 코틀린이 타입을 추론하는 과정에서 여러분이 예상한 타입과 컴파일러가 추론한 타입이 다를 경우 이를 알려준다는 뜻이다.
하지만 이보다 더 잘 할 수 있다. 우선, Price와 Weight에 검증을 추가한다. 클래스 안에서 항등원으로 0 값을 사용할 때를 제외하면 두 타입 모두 0을 값으로 생성할 수는 없다. 팩터리 함수와 비공개 생성자를 사용하면 이런 동작을 구현할 수 있다. 다음은 Price의 경우다.
data class Price private constructor (private val value: Double) { override fun toString() = value.toString() operator fun plus(price: Price) = Price(this.value + price.value) operator fun times(num: Int) = Price(this.value * num) companion object { val identity = Price(0.0) operator fun invoke(value: Double) = if (value > 0) Price(value) else throw IllegalArgumentException("Price must be positive or null") } }