Подтвердить что ты не робот

Почему этот тип неявного преобразования является незаконным?

Я пишу следующее неявное преобразование в scala:

  implicit def strToInt2(str: String):Int = {
    str.toInt
  }

Но это вызывает ошибку компиляции:

<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
           ^

Если я удалю возвращаемый тип, просто объявите его следующим образом:

  implicit def strToInt2(str: String) = {
    str.toInt
  }

Он успешно компилируется. Может ли кто-нибудь сказать мне, какая разница между ними?

4b9b3361

Ответ 1

Хорошо, начнем с начала, почему он не работает в первом случае:

  • Вы пытаетесь определить неявный метод, который преобразует String в Int, и для этого вы вызываете toInt.
  • К сожалению, toInt не является частью класса String. Таким образом, компилятор должен найти неявное преобразование str в то, что имеет метод toInt:Int.
  • К счастью, Predef.augmentString преобразует String в StringOps, который имеет такой метод.
  • Но тип Int также имеет такой метод, и если вы определяете тип возврата, метод strToInt2 можно вызывать рекурсивно, а поскольку метод неявный, его можно применить для преобразования чего-либо с помощью toInt:Int.
  • Компилятор не знает, какой неявный метод использовать (между вашими и Predef.augmentString и выдает ошибку.

Во втором случае, когда вы опускаете возвращаемый тип, функция strToInt2 не может быть рекурсивной, и больше нет двух кандидатов для преобразования String.

НО, если после этого определения вы попытаетесь: "2".toInt, ошибка вернется: теперь у вас есть два способа получить что-то с помощью функции toInt:Int, если у вас есть String.