开发者

Implicit conversion from String to Int in scala 2.8

Is there something I've got wrong with the following fragment:-

object Imp {
  implicit def string2Int(s: String): Int = s.toInt

  def f(i: Int) = i

  def main(args: Array[String]) {
    val n: Int = f("666")
  }
}

I get the following from the 2.8 compiler:-

Information:Compilation completed with 1 error and 0 warnings

Information:1 error

Information:0 warnings

...\scala-2.8-tests\src\Imp.scala

E开发者_运维知识库rror:Error:line (4)error: type mismatch;

found : String

required: ?{val toInt: ?}

Note that implicit conversions are not applicable because they are ambiguous:

both method string2Int in object Imp of type (s: String)Int

and method augmentString in object Predef of type (x:String)scala.collection.immutable.StringOps

are possible conversion functions from String to ?{val toInt: ?}

implicit def string2Int(s: String): Int = s.toInt


What is happening is that Java does not define a toInt method on String. In Scala, what defines that method is the class StringOps (Scala 2.8) or RichString (Scala 2.7).

On the other hand, there is a method toInt available on Int as well (through another implicit, perhaps?), so the compiler doesn't know if it is to convert the string to StringOps, through the defined implicit, or to Int, through your own implicit.

To solve it, call the implicit explicitly.

object Imp {
  implicit def string2Int(s: String): Int = augmentString(s).toInt

  def f(i: Int) = i

  def main(args: Array[String]) {
    val n: Int = f("666")
  }
}


There is already an implicit conversion in scope, from scala.Predef. You don't need to declare your own implicit conversion to add a toInt method to a String. You have 3 options (I'd go for the last one!):

  • Change your method name to something like asInt
  • Unimport the conversion in Predef
  • Don't bother defining your own and use instead the toInt that comes bundled with the scala library

Note that scala will only make use of an in-scope implicit conversion if it is unique.


I think I have a workaround.

If I create a RichString from the String argument, the implicit conversion occurs from RichString to Int using the implicit method I provide (this works for 2.7.x and 2.8). If I remove my implicit I get a type error.

object Imp {

  implicit def string2Int(rs: RichString): Int = rs.toInt

  def f(i: Int) = i

  def main(args: Array[String]) {
    val n: Int = f(new RichString("666"))

    println(n)
  }
}

I'm still confused as to why both implicits came into scope and clashed when I provided an implicit and as to why the Predef one didn't come into scope when I didn't provide one for String to Int. I suppose the question about an implicit conversion from String to Int remains open.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜