清除类型后,隐式如何找到要使用泛型调用的正确方法?

时间:2019-05-12 10:30:37

标签: scala generics types implicit erasure

在下面的代码中,我有一个函数test,该函数接受一个类型为magnet的对象,并且我有两个隐式方法将List [Int]转换为magnet,另一个将List [String]转换为磁铁。 / p>

如果由于运行时类型擦除而导致JVM应该释放泛型中的类型,那么在我下面的代码中,方法fromListIntfromListString都将看起来像List [Any],对吗? 因为当我用相同的名字命名两个函数时,我得到了错误error: double definition:,这表明List [Int]和List [String]被认为是相同的。

在我通过List(0)和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

2 个答案:

答案 0 :(得分:2)

隐式在编译时解决,而不是在运行时解决。在编译时,没有擦除任何内容。完整类型信息可供编译器使用。

在REPL中,每次键入一行代码时,都在运行它之前对其进行编译。 test(List(0))被编译器转换为test(fromListInt(List(0)))之类的东西,并且被编译,这就是您看到的行为。 test(List("0"))被编译器转换为类似test(fromListString(List("0")))的东西,这就是您在此处看到的行为。

答案 1 :(得分:1)

隐式在编译时解决。在编译时,类型尚未删除。

test(List(0))实际上是test(fromListInt(List(0)))test(List("0"))实际上是test(fromListString(List("0")))