演算子オーバーロードを使うと、何らかの数値情報を扱うようなドメインオブジェクト同士で演算を行う必要がある場合、ドメインオブジェクト自体を数値型のように扱えて便利だと思います。
Money.scala
case class Money(private val value: BigDecimal) {
def +(that: Money): Money = new Money(this.value + that.value)
def -(that: Money): Money = new Money(this.value - that.value)
def >(that: Money): Boolean = this.value > that.value
def >=(that: Money): Boolean = this.value >= that.value
def <(that: Money): Boolean = this.value < that.value
def <=(that: Money): Boolean = this.value <= that.value
override def toString = this.value.toString
}
このようにするとMoneyオブジェクトを使う側からは以下の様な感じで利用可能です。
MoneySpec.scala
import org.specs2.mutable._
class MoneySpec extends Specification {
"Money" should {
"Moneyの加算" in {
Money(100) + Money(200) must_== Money(300)
}
"Moneyの減算" >> {
Money(200) - Money(100) must_== Money(100)
}
"Moneyの比較" >> {
"==" in {
val a = Money(100)
val b = Money(100)
val c = Money(100)
a == b must_== true
b == a must_== true
b == c must_== true
a == c must_== true
a == Money(101) must_== false
}
">" in {
Money(100) > Money(99) must_== true
Money(100) > Money(100) must_== false
}
">=" in {
Money(100) >= Money(99) must_== true
Money(100) >= Money(100) must_== true
Money(100) >= Money(101) must_== false
}
"<" in {
Money(100) < Money(100) must_== false
Money(100) < Money(101)
}
">=" in {
Money(100) <= Money(101) must_== true
Money(100) <= Money(100) must_== true
Money(100) <= Money(99) must_== false
}
}
"Moneyを文字列に変換する" in {
val Money100 = Money(100)
Money100.toString must_== "100"
}
}
}
Caluculator.scala
object Caluculator extends App {
val walet:List[Money] = Money(100) :: Money(200) :: Money(300) :: Nil
val sum:Money = (Money(0) /: walet) (_ + _)
println(sum.toString)
}
Moneyオブジェクト同士を+したり-するのは直感的なはず。