Ответ 1
Во-первых, давайте посмотрим на их объявление:
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))