kotlin operator invoke 로 데이터 검증 하기!
상황 설명
Price
의 경우 0원 생성할 수 없지만, 시작값을 위해서는 1개는 존재 해야 합니다.
이를 어떻게 처리 할까 고민했었는데 아래와 같은 해법이 있네요.
코드 구현
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) // 0원 구현 private constructor 이기 때문에 외부에서는 생성 못함
// 생성시 호출되는 invoke 함수를 companion으로만 제공
operator fun invoke(value: Double) =
if (value > 0)
Price(value)
else
throw IllegalArgumentException("Price must be positive or null")
}
}
fun main() {
println(Price.identity) // 0.0 출력
println(Price(5.0) + Price(4.8)) // 9.8 출력
println(Price(5.0) * 3) // 15.0 출력
println(Price(-0.0)) // Exception in thread "main" java.lang IllegalArgumentException: Price must be positive or null
println(Price(3.12) * 3.2) // The floating-point literal does not conform to the expected type Int
println(Price(5.0) * Price(4.8)) // Type mismatch: inferred type is Price but Int was expected
println(Price(5.0) - 3) // Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public inline operator fun BigDecimal.minus(other: BigDecimal):
}
operator
plus
, times
를 구현해서 위와 같이 사용 할 수 있습니다.
operator 종류
산술 연산자
| 함수 이름 | 연산자 | 설명 | |———–|——–|———-| | plus | + | 더하기 | | minus | - | 빼기 | | times | * | 곱하기 | | div | / | 나누기 | | rem | % | 나머지 연산 |
예제 코드
data class Price (private val value: Double) {
operator fun plus(price: Price) = Price(this.value + price.value)
operator fun times(num: Int) = Price(this.value * num)
}
fun main() {
println(Price(5.0) + Price(4.8))
println(Price(5.0) * 3)
}
대입 연산자
함수 이름 | 연산자 | 설명 |
---|---|---|
plusAssign | += | 더해서 대입 |
minusAssign | -= | 빼서 대입 |
timesAssign | *= | 곱해서 대입 |
divAssign | /= | 나눠서 대입 |
예제 코드
data class Price(private var value: Double) {
operator fun plusAssign(price: Price) {
this.value += price.value
}
}
fun main() {
val p1 = Price(5.0)
val p2 = Price(4.8)
p1 += p2
println(p1) // Output: Price(value=9.8)
}
단항 연산자
함수 이름 | 연산자 | 설명 - object가 변수명 |
---|---|---|
unaryPlus | + | +object |
unaryMinus | - | -object |
not | ! | !object |
inc | ++ | ++object |
dec | – | –object |
예제 코드
data class Price(private var value: Double) {
operator fun inc(): Price {
value++
return this
}
operator fun dec(): Price {
value--
return this
}
}
fun main() {
var p1 = Price(5.0)
println("Original p1: $p1")
p1++
println("After incrementing: $p1")
p1--
println("After decrementing: $p1")
}