I want to have 2 implicit comvertors in scala
To convert int to float
implicit def String2Int(v: String): Int = Integer.parseInt(v)
The above works but when I write below
implicit def String2Float(v: String): Float = v.toFloat
It gives compile error cannot resolve symbol to Float
Can we not have 2 implicit converters in one file?
In scala, String
does not have toInt, toFloat
, etc methods. Where are they taken from?
Scala has Predef object which is imported implicitly in every source (even if you are not importing it).
Predef has the following method:
@inline implicit def augmentString(x: String): StringOps = new StringOps(x)
So it implicitly converts any value of type String
to StringOps
.
StringOps
defines methods:
def toInt: Int = java.lang.Integer.parseInt(toString)
def toFloat: Float = java.lang.Float.parseFloat(toString)
...
So when you write str.toFloat
- the compiler actually converts String
to StringOps
and calls the appropriate method.
Ok. What is the problem with your code?
implicit def String2Float(v: String): Float = v.toFloat
Compiler tries to find something that has .toFloat
, it finds it in StringOps
and in Float
via String2Float
method. ( Float
also has toFloat
method).
Compiler "didn't add" the method toFloat
(of Predef
) to String
because it cannot decide which implicit conversion to apply and implicit conversion from String
to StringOps
is broken.
So String
does not have toFoat
method anymore and that's why you have error ( cannot resolve symbol to Float )
(Actually, you should have 2 errors: Note that implicit conversions are not applicable because they are ambiguous: ... AND value toFloat is not a member of String )
Solution is to use
implicit def String2Float(v: String): Float = java.lang.Float.parseFloat(v)
Like you did in Int
case.
Now it converts String
to Float
directly, without implicit conversions (like it was in v.toFloat
case)
PS Thank @Dima for pointing to mistake in my answer.
You can define String2Float as:
implicit def String2Float(v: String): Float = {
val i:Int = v
i.toFloat
}
or pass implicit converter as:
implicit def String2Float(v: String)(implicit f: String => Int): Float = {
v.toFloat
}
or get the converter instance implicitly:
implicit def String2Float(v: String): Float = {
val f = implicitly[String => Int]
f(v).toFloat
}
In this case compiler resolves everything successfully
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.