結論
Ordered[T]
は自身に継承し、比較可能にするOrdering[T]
は自身を変えることなく、外側から変換を提供する
Ordered[T]
例えば、単純に比較するだけのクラスを作る。このクラスは Ordered[T]
を継承していて、compare
メソッドを実装する必要がある。
参考: Scala Standard Library 2.13.5 - scala.math.Ordered
case class MyOrderedNum(value: Int) extends Ordered[MyOrderedNum] { override def compare(that: MyOrderedNum): Int = { if (this.value < that.value) -1 else if (that.value < this.value) 1 else 0 } }
こんな感じで呼び出せる。
assert(MyOrderedNum(10) > MyOrderedNum(2)) // => success!
Ordering[T]
implicitなパラメータとして Ordering[T]
を与えている。クラスの外側で Ordering[T]
の実装を提供することで、比較ができるようになる。この方法だと、クラス自体を変えることなく、外側から実装を追加することができる。
参考: Scala Standard Library 2.13.5 - scala.math.Ordering
ScalaのInt
, String
などもこちらの方法を用いて比較可能にされている。これは、Int
のようなプリミティブなクラスに関しては AnyVal
を継承しているだけに留めたく、他のクラスを継承したくないという思想があるらしい。
参考: scala - Why does Int not inherit/extend from Ordered[Int] - Stack Overflow
case class MyOrderingNum(value: Int)(implicit ord: Ordering[MyOrderingNum]) { def >(that: MyOrderingNum): Boolean = ord.compare(this, that) > 0 } implicit object MyOrdering extends Ordering[MyOrderingNum] { override def compare(x: MyOrderingNum, y: MyOrderingNum): Int = { if (x.value < y.value) -1 else if (y.value < x.value) 1 else 0 } }
こんな感じで呼び出せる。
assert(MyOrderingNum(10) > MyOrderingNum(2)) // => success!
Appendix
Numeric[T]
は Ordering[T]
を継承していて、他にも四則演算をサポートしている。
trait Numeric[T] extends Ordering[T]
参考: Scala Standard Library 2.13.5 - scala.math.Numeric