scala.math.Integral的方法mkNumericOps
和mkOrderingOps
做了什么以及我们如何使用它们?
我知道函数和对象方法可以声明为implicit
并用于隐式转换。但是我不明白为什么 traits methods 被声明为implicit
。
BTW,类方法也可以声明为implicit
吗?
答案 0 :(得分:8)
首先,让我们看看他们的声明:
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))