我不明白以下代码(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])
如果我在 Pimp 类中为 Option[Double] 添加显式的 < 操作符:
def <(that : Option[Double]) = x < that.get
一切编译都很好。
现在,根据我对Scala隐式转换规则的理解,这很合理:
- 编译器知道Double上没有接受Option[Double]的'<'运算符
- 它考虑使用Pimp1进行隐式转换。
- 如果Pimp1有适当的运算符,则可以工作,否则会生成错误。
- 重要的是,这证明了编译器不考虑应用第二个(可用的)隐式转换,从Option[Double]到Pimp。
这就是我希望的工作方式。
然而,这似乎与第一个示例相矛盾,其中:
- 编译器发现Double上没有pluss方法。
- 编译器尝试使用Pimp进行隐式转换,该方法确实具有此类方法。
- 但是,为了使运算符起作用,编译器必须对参数应用第二个隐式转换,将其转换为Pimp。
根据上面的逻辑,这应该无法编译,但实际上可以。隐式转换规则是否会对不存在的方法和不匹配的方法进行不同处理?