Вопрос про scala.math.Integral
Что делают методы mkNumericOps
а такжеmkOrderingOps
из scala.math.Integral делать и как мы можем их использовать?
Я понимаю, что функции и методы объекта могут быть объявлены implicit
и используется для неявного преобразования. Однако я не понимаю, почему методы признаков объявлены implicit
,
Кстати, могут ли быть объявлены методы класса implicit
тоже?
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))