【问题标题】:How does generics work in scala REPL?泛型如何在 scala REPL 中工作?
【发布时间】:2014-01-19 17:05:43
【问题描述】:

我知道擦​​除类型是什么。所以,我认为 scala REPL 无法准确检测到泛型类型。
正如我上面提到的,scala 无法像这样在模式匹配中检测泛型类型:

    case list: List[Int]

但是当我声明 List 类型值时,scala 会检测到包含的泛型类型。

    scala> val a = List(1,2,3)
    a: List[Int] = List(1, 2, 3)

这怎么可能?

【问题讨论】:

    标签: scala generics scala-2.10


    【解决方案1】:
    val a = List(1,2,3)
    

    这相当于:

    val a = List.apply[Int](1,2,3)
    

    List.apply[Int](...) 的结果类型为List[Int],因此类型推断器将此类型分配给标识符a。这发生在编译期间。 REPL 不会在运行时“检测”类型。

    这与模式匹配不同:

    val a: Any = ...
    a match {
      case list: List[Int] => ...
    }
    

    在这里,我们有一个值a,我们没有任何类型信息。所以我们试图检查它是什么类型,但现在我们在 runtime 中执行此操作。在这里,我们确实无法确定确切的类型。我们在这里能做的最好的就是匹配List[_]

    总结: 当您在 REPL 中键入一些代码时,它首先被编译成字节码,然后被评估。显示的类型信息来自编译阶段,因此不会受到类型擦除的影响。

    【讨论】:

      【解决方案2】:

      当你写作时:

      val a = List(1,2,3)
      

      Scala 在编译期间使用类型推断来查找最接近的匹配类型。本质上它会为你重写它:

      val a: List[Int] = ...
      

      它会在编译时使用这个参数类型信息来检查你的代码并在之后擦除它,这样你就可以在你的程序中得到List[_]。这是因为 JVM 以这种方式工作 - 类型擦除。

      当您在运行时对列表进行模式匹配时,它的类型信息将被删除,因此任何List 都会匹配。 Scala 编译器会在编译期间发出警告。

      这在 REPL 和常规 compile->run 循环中的工作方式相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-01
        相关资源
        最近更新 更多