I am trying to create an implicit conversion from any type (say, Int) to a String...
An implicit conversion to String means RichString methods (like reverse) are not available.
implicit def intToString(i: Int) = String.valueOf(i)
100.toCharArray // => Array[Char] = Array(1, 0, 0)
100.reverse // => error: value reverse is not a member of Int
100.length // => 3
An implicit conversion to RichString means String methods (like toCharArray) are not available
implicit def intToRichString(i: Int) = new RichString(String.valueOf(i))
100.reverse // => "001"
100.toCharArray // => error: value toCharArray is not a member of Int
100.length // => 3
Using both implicit conversions means duplicated methods (like length) are ambiguous.
implicit def intToString(i: Int) = String.valueOf(i)
implicit def intToRichString(i: Int) = new RichString(String.valueOf(i))
100.toCharArray // => Array[Char] = Array(1, 0, 0)
100.reverse // => "001"
100.length // => both method intToString in object $iw of type
// (Int)java.lang.String and method intToRichString in object
// $iw of type (Int)scala.runtime.RichString are possible
// conversion functions from Int to ?{val length: ?}
So, is it possible to implicitly convert to String and still support all String and RichString methods?
Either make a huge proxy class, or suck it up and require the client to disambiguate it:
100.asInstanceOf[String].length
I'm confused: can't you use
.toString
on any type anyway thus avoiding the need for implicit conversions?The only option I see is to create a new String Wrapper class MyString and let that call whatever method you want to be called in the ambiguous case. Then you could define implicit conversions to MyString and two implicit conversions from MyString to String and RichString, just in case you need to pass it to a library function.
The accepted solution (posted by Mitch Blevins) will never work: downcasting
Int
toString
usingasInstanceOf
will always fail.One solution to your problem is to add a conversion from any String-convertible type to
RichString
(or rather, toStringOps
as it is now named):Then define your conversion(s) to string as before:
As of Scala 2.8, this has been improved. As per this paper (§ Avoiding Ambiguities) :
See that other paper (§6.5) for an example.
I don't have a solution, but will comment that the reason
RichString
methods are not available after yourintToString
implicit is that Scala does not chain implicit calls (see 21.2 "Rules for implicits" in Programming in Scala).If you introduce an intermediate
String
, Scala will make the implict converstion to aRichString
(that implicit is defined inPredef.scala
).E.g.,