【问题标题】:Type Erasure in ScalaScala中的类型擦除
【发布时间】:2016-07-25 14:49:52
【问题描述】:

我对这里发生的事情感到很困惑:

import scala.collection.immutable._

object Main extends App {
  sealed trait Node

  sealed trait Group

  case class Sheet(
    val splat: String,
    val charname: String, 
    val children: ListMap[String, Node],
    val params0: ListMap[String, Param], //params0 to separate sheet-general parameters

    val note: Option[Note]
    ) extends Node with Group

  case class Attributes(val name: String) extends Node with Group

  case class Param(val name: String, val value: String) extends Node
  case class Note(val note: String) extends Node

我有三个版本的替换功能 - 最后一个是我真正尝试编写的版本,其他的只是调试。

  class SheetUpdater(s: Sheet) {    
    def replace1[T <: Group](g: T): Unit = {
      s.children.head match {
        case (_, _:Sheet) =>
        case (_, _:Attributes) =>
      }
    }
  }

此版本不会引发任何警告,因此显然我可以在运行时访问 s.children 的类型。

  class SheetUpdater(s: Sheet) {
    def replace2[T <: Group](g: T): Unit = {
      g match {
        case _:Sheet =>
        case _:Attributes =>
      }
    }
  }

这个版本也没有,所以显然g 的类型的详细信息在运行时可用...

  class SheetUpdater(s: Sheet) {
    def replace3[T <: Group](g: T): Unit = {
      s.children.head match {
        case (_, _:T) => //!
        case (_, _:Attributes) =>
      }
    }
  }

...但即便如此,这最终还是给了我可怕的Abstract type pattern T is unchecked since it is eliminated by erasure 警告。这是怎么回事?

【问题讨论】:

    标签: scala type-erasure


    【解决方案1】:

    在 Scala 中,泛型在运行时被擦除,这意味着 List[Int]List[Boolean] 的运行时类型实际上是相同的。这是因为 JVM 作为一个整体会擦除泛型类型。这一切都是因为 JVM 希望在首次引入泛型时保持向后兼容......

    在 Scala 中有一种使用 ClassTag 的方法来解决这个问题,这是一个隐式参数,然后可以使用您正在使用的任何泛型进行线程化。

    您可以将: ClassTag 视为将泛型的类型作为参数传递。 (它是传递ClassTag[T] 类型的隐式参数的语法糖。)

    import scala.reflect.ClassTag
    
    class SheetUpdater(s: Sheet) {
      def replace3[T <: Group : ClassTag](g: T): Unit = {
        s.children.head match {
          case (_, _:T) => //!
          case (_, _:Attributes) =>
        }
      }
    }
    

    Newer answers of this question have more details.

    【讨论】:

    • 我想我的问题是“我的通用产品在哪里”?这不像我匹配 List[T] 或类似的东西,所以...
    • @linkhyrule5 通用是s.children: ListMap[String, Node]
    • 当然,但我分解了 - 我正在匹配孩子,这仍然应该是很好的类型。
    • 原来是元组。
    猜你喜欢
    • 2012-05-28
    • 2020-07-27
    • 2012-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    相关资源
    最近更新 更多