This happens due to member shadowing. The imported toString
is not available in the scope where you expect the implicit conversion to happen. Let's see how it works...
First let's check that implicit works:
scala> object FooConversions {
| implicit def toString(foo: Foo): String = foo.toString
|
| val x: String = Foo("bob")
| }
defined object FooConversions
Yes it does in the original/definition scope.
Now let's try to see if the imported method toString
is available:
object FooConversions {
implicit def toString(foo: Foo): String = foo.toString
}
import FooConversions._
val y: String = toString(Foo("bob"))
<console>:28: error: too many arguments for method toString: ()String
val y: String = toString(Foo("bob"))
It's not available - it's being shadowed by the toString
of the enclosing object. In REPL for the code to compile Scala puts everything in some magic object. In real life code will reside in some object/class.
Trying to call toString
explicitly to check if it could potentially work:
scala> val y: String = FooConversions.toString(Foo("bob"))
y: String = Foo(bob)
No problem here obviously.
So the solution is either (1) to rename toString
to some other name that can't be potentially shadowed:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> case class Foo(name: String)
defined class Foo
scala> object FooConversions {
| implicit def toStr(foo: Foo): String = foo.toString
| }
defined object FooConversions
scala> import FooConversions._
import FooConversions._
scala> val x: String = Foo("bob")
x: String = Foo(bob)
or (2) to redefine an implicit (sucks):
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> case class Foo(name: String)
defined class Foo
scala> object FooConversions {
| implicit def toString(foo: Foo): String = foo.toString
| }
defined object FooConversions
scala> implicit def toStr(foo: Foo) = FooConversions.toString(foo)
toStr: (foo: Foo)String
scala> val x: String = Foo("bob")
x: String = Foo(bob)
p.s. This is not an issue of implicit lookup or implicit scope, but an issue of shadowing/hiding of imported members.