'1 * BigInt(1)'如何工作?我怎么能这样做?

时间:2011-10-04 12:24:35

标签: math scala numeric implicit

我尝试实现一些数字类型,我遇到了

的问题
mynum * 1

有效,但不是

1 * mynum

我尝试定义像这样的隐式转换

case class Num(v: Int) {
  def * (o: Int) = new Num(v*o)
}

implicit def int2Num(v: Int) = Num(v)

但它似乎不起作用,因为我总是得到以下错误:

scala> 1 * new Num(2)
<console>:14: error: overloaded method value * with alternatives:
  (x: Double)Double <and>
  (x: Float)Float <and>
  (x: Long)Long <and>
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int
 cannot be applied to (Num)
              1 * new Num(2)
                ^

另一方面

1 * BigInt(1)

有效,所以必须有办法,但在查看代码时我无法确定解决方案。

使它运作的机制是什么?

编辑:我根据我遇到的实际问题Why is the implicit conversion not considered in this case with generic parameters?创建了一个新问题。

2 个答案:

答案 0 :(得分:9)

当应用程序a.meth(args)失败时,编译器会搜索从a到具有方法meth的隐式视图。任何符合A => { def meth(...) }的隐式值或方法都可以。如果找到,则代码将重写为view(a).meth(args)

它在哪里?首先,它查看当前范围,由本地定义的含义和导入的含义组成。

(实际上是搜索的第二阶段,其中考虑了带有名称参数的转换方法,但这对于这个答案并不重要。)

如果失败,则查看隐式范围。这包括我们正在搜索的类型的“部分”的伴随对象。在这种情况下,我们在A => { def meth(...) }之后,所以我们只看A的伴随对象(及其超类型)。

在Scala主干中,隐式作用域为extended a tiny bit,以包含类型的参数的伴随对象。不确定是否已经在2.9.1中,也许友好的读者会为我解决这个问题并更新这个答案。

因此1 + BigInt(2)已扩展为BigInt.int2bigInt(1) + BigInt(2)

答案 1 :(得分:7)

我认为你在Name类中缺少*方法,它接受一个Number作为参数。