8

我不明白我在以下代码(Scala 2.9)中看到的明显矛盾的行为:

class Pimp1(val x : Double) {
  def pluss(that : Pimp1) = x + that.x
  def <(that : Pimp1) = x < that.x
}

object Pimp1 {
implicit def d2pimp(d : Double) = new Pimp1(d)
implicit def d2pimp(od : Option[Double]) = new Pimp1(od.get)
} 

object Scratch2 extends App {
    import Pimp1._

    5.0.pluss(Some(5.0))
    5.0 < Some(5.0)
}

'5.0.pluss(Some(5.0))' 行编译,但它后面的行没有编译并出现以下错误消息:

重载方法值 < 有替代方案: (x: Double)Boolean (x: Float)Boolean (x: Long)Boolean (x: Int)Boolean (x: Char)Boolean (x: Short)Boolean (x: Byte)Boolean 不能应用于 (Some[Double])

如果我将显式 < 运算符添加到采用 Option[Double] 的 Pimp 类中:

def <(that : Option[Double]) = x < that.get

一切都编译得很好。

现在,按照我理解 Scala 隐式转换规则的方式,这很有意义:

  1. 编译器知道 Double 上没有接受 Option[Double] 的 '<' 运算符
  2. 它考虑到 Pimp1 的隐式转换。
  3. 如果 Pimp1 有合适的运算符,它就会工作,否则会产生错误。
  4. 重要的是,这表明编译器考虑应用第二个(可用的)隐式转换,从 Option[Double] 到 Pimp。

这就是我期望的工作方式。

但是,这似乎与第一个示例相矛盾,其中:

  1. 编译器发现 Double 上没有 pluss 方法。
  2. 编译器尝试隐式转换为 Pimp,它确实有这样的方法。
  3. 但是,为了使运算符工作,编译器必须对参数应用第二次隐式转换,以将其转换为 Pimp。

根据上面的逻辑,这不应该编译,但确实可以。隐式转换规则是否对不存在的方法和不匹配的方法有不同的处理?

4

1 回答 1

5

这对我来说很有意义。第一个,它的工作原理是这样的:

Double 有加号方法吗?不,我们可以将其隐式转换为可以执行的操作吗?是的。好的,现在我想应用 pluss 方法。它需要一个选项吗?不可以。我可以隐含地将 Option 转换为它确实需要的东西吗?是的。

第二个是这样的:

Double 有 < 方法吗?是的。它需要一个选项吗?不,我可以将 Option 隐式转换为 < 确实需要的东西吗?不。

于 2012-10-04T20:27:58.523 回答