Во-первых, давайте посмотрим на их объявление:
implicit def mkNumericOps (lhs: T): IntegralOps
implicit def mkOrderingOps (lhs: T): Ops
Тот факт, что они неявные, означает, что их цель состоит в том, чтобы обеспечить некоторое автоматическое значение или преобразование. Обратите внимание, что они оба преобразуются из T
в какой-либо другой тип, где T
является параметром типа признака: Integral[T]
.
Итак, если у вас есть Integral[Int]
, то mkNumericOps
даст вам автоматическое преобразование из Int
в IntegralOps
. Это означает, что вы сможете вызывать методы из IntegralOps
или Ops
для Int
(или любого другого типа вашего Integral
).
Теперь давайте посмотрим, что это за методы:
def % (rhs: T): T
def * (rhs: T): T
def + (rhs: T): T
def - (rhs: T): T
def / (rhs: T): T
def /% (rhs: T): (T, T)
def abs (): T
def signum (): Int
def toDouble (): Double
def toFloat (): Float
def toInt (): Int
def toLong (): Long
def unary_- (): T
Это от IntegralOps
, что расширяет Ops
. Интересно, что многие из них уже определены в Int
! Итак, как и почему их можно использовать? Вот пример:
def sum[T](list: List[T])(implicit integral: Integral[T]): T = {
import integral._ // get the implicits in question into scope
list.foldLeft(integral.zero)(_ + _)
}
Итак, для любого типа T
, для которого есть неявно доступный Integral[T]
, вы можете передать список этого типа на sum
.
Если, с другой стороны, я определил свой метод для типа Int
, я мог бы написать его без Integral
. С другой стороны, я не могу написать что-то, что будет работать как для Int
, так и для Long
и BigInt
, потому что они не имеют общего предка, определяющего метод +
(намного меньше "нуля") .
foldLeft
выше эффективно переводится как это:
list.foldLeft(integral.zero)((x, y) => mkNumericOps(x).+(y))