关于scala.math.Integral的问题

时间:2011-03-31 20:37:11

标签: scala implicit-conversion

scala.math.Integral的方法mkNumericOpsmkOrderingOps做了什么以及我们如何使用它们?

我知道函数和对象方法可以声明为implicit并用于隐式转换。但是我不明白为什么 traits methods 被声明为implicit

BTW,类方法也可以声明为implicit吗?

1 个答案:

答案 0 :(得分:8)

首先,让我们看看他们的声明:

implicit def mkNumericOps (lhs: T): IntegralOps
implicit def mkOrderingOps (lhs: T): Ops

它们是隐含的意味着它们的目标是提供一些自动值或转换。请注意,它们都从T转换为其他类型,其中T是特征的类型参数:Integral[T]

因此,如果您有Integral[Int],则mkNumericOps会自动从Int转换为IntegralOps。这意味着您可以在IntegralOps上调用来自OpsInt的方法(或者您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的情况下编写它。另一方面,我不能写出适用于IntLong以及BigInt的内容,因为它们不共享定义方法的共同祖先+ (更不用说“零”)。

上面的foldLeft被有效地翻译为:

list.foldLeft(integral.zero)((x, y) => mkNumericOps(x).+(y))