我对这里发生的事情感到困惑:
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) => } } }
…但即便如此,这最终会让我感到害怕的抽象类型模式T未经检查,因为它被擦除警告消除了.这里发生了什么?
解决方法
在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) => } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。