In my code below, I have a function test
that takes in a object of type magnet and I have two implicit methods converting List[Int] to magnet and the other converting List[String] to magnet.
If JVM is supposed to loose the types in generics due to type erasure at run time, In my below code both the methods fromListInt
and fromListString
will look like List[Any] right?
Because when I name both functions with same name I got the error error: double definition:
suggesting that both List[Int] and List[String] are considered same.
how are the correct implicit methods found in this case when I pass List(0) and List("0") ?
scala> trait magnet {
| def printSomething: Unit
| }
defined trait magnet
scala> object magnet {
| implicit def fromListInt(future: List[Int]): magnet = {
| new magnet { def printSomething: Unit = println("test int") }
| }
| implicit def fromListString(future: List[String]): magnet = {
| new magnet { def printSomething: Unit = println("test string") }
| }
| }
defined object magnet
scala> def test(in: magnet): Unit = {
| in.printSomething
| }
test: (in: magnet)Unit
scala> import magnet._
import magnet._
scala> test(List(0))
test int
scala> test(List("0"))
test string
Implicits are resolved at compile time, not at runtime. At compile time, nothing has been erased. Full type information is available to the compiler.
In a REPL, every time you type a line of code, you are compiling it before you are running it. test(List(0))
gets converted by the compiler to something like test(fromListInt(List(0)))
, and that what is compiled, and so that is the behavior you see. test(List("0"))
gets converted by the compiler to something like test(fromListString(List("0")))
, and so that is the behavior you see there.