为什么这种隐式转换是非法的?

zjf*_*fdu 17 scala implicit-conversion

我在scala中编写以下隐式转换:

  implicit def strToInt2(str: String):Int = {
    str.toInt
  }
Run Code Online (Sandbox Code Playgroud)

但它上升了这个编译错误:

<console>:9: error: type mismatch;
 found   : str.type (with underlying type String)
 required: ?{val toInt: ?}
Note that implicit conversions are not applicable because they are ambiguous:
 both method augmentString in object Predef of type (x: String)scala.collection.
immutable.StringOps
 and method toi in object $iw of type (str: String)Int
 are possible conversion functions from str.type to ?{val toInt: ?}
           str.toInt
           ^
Run Code Online (Sandbox Code Playgroud)

如果我删除了返回类型,只需声明它:

  implicit def strToInt2(str: String) = {
    str.toInt
  }
Run Code Online (Sandbox Code Playgroud)

它编译成功.谁能告诉我两者之间有什么区别?

Nic*_*las 17

好吧,让我们从头开始,为什么在第一种情况下失败:

  1. 您尝试定义一个隐式方法,将您转换String为an Int并将其调用toInt.
  2. 不幸的是,toInt不是String课程的一部分.因此,编译器需要找到一个隐式转换str为具有toInt:Int方法的东西.
  3. 幸运的是,Predef.augmentString将a转换String为a StringOps,其中有这样的方法.
  4. 但是Int类型也有这样的方法和AS你定义一个返回类型,该方法strToInt2可以递归调用,并且由于该方法是隐式的,它可以应用于使用toInt:Int函数转换某些东西.
  5. 编译器不知道使用哪个隐式方法(在您和/之间Predef.augmentString抛出错误).

在第二种情况下,当你省略返回类型时,strToInt2函数不能递归,并且不再有两个候选者进行转换String.

但是如果在这个定义之后,你尝试:"2".toInt,错误就回来了:你现在有两种方法可以获得带有toInt:Int函数的东西String.