次のコード (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 の暗黙的な変換規則を理解している方法では、これは完全に理にかなっています。
- コンパイラは、Double に Option[Double] を受け入れる '<' 演算子がないことを認識します。
- Pimp1 への暗黙的な変換を考慮します。
- Pimp1 に適切な演算子がある場合は機能しますが、そうでない場合はエラーが発生します。
- 重要なことに、これはコンパイラがOption[Double] から Pimp への 2 番目の (利用可能な) 暗黙的な変換を適用することを考慮していないことを示しています。
これが私が物事がうまくいくと期待した方法です。
ただし、これは最初の例と矛盾しているようです。
- コンパイラは、Double に pluss メソッドがないことを認識します。
- コンパイラは、そのようなメソッドを持つ Pimp への暗黙的な変換を試みます。
- ただし、演算子を機能させるために、コンパイラは引数に 2 番目の暗黙的な変換を適用して、それを Pimp に変換する必要があります。
上記のロジックによると、これはコンパイルされるべきではありませんが、コンパイルされます。暗黙的な変換規則は、存在しないメソッドと一致しないメソッドを異なる方法で扱いますか?