在Scala 2中,对象的大部分泛型类型信息在运行时都会被擦除。目前,所有三个二进制执行环境(JVM、javascript和LLVM)都遵守这一行为,它们只是在元数据格式的细节上有所不同。
在极少数情况下,如果它导致关键数据丢失,或者触发了罕见的二进制错误。应该使用一种机制来保留伴随数据结构中声明的类型信息。下面的代码给出了Scala 2中此类数据结构的一个简短示例:
import scala.reflect.runtime.universe
import scala.collection.concurrent.TrieMap
import scala.language.implicitConversions
case class Unerase[T](self: T)(
implicit
ev: universe.TypeTag[T]
) {
import Unerase._
cache += {
val inMemoryId = System.identityHashCode(this)
inMemoryId -> ev
}
}
object Unerase {
lazy val cache = TrieMap.empty[Int, universe.TypeTag[_]]
def get[T](v: T): Option[universe.TypeTag[T]] = {
val inMemoryId = System.identityHashCode(v)
cache.get(inMemoryId).map { tt =>
tt.asInstanceOf[universe.TypeTag[T]]
}
}
implicit def unbox[T](v: Unerase[T]): T = v.self
implicit def box[T](v: T)(
implicit
ev: universe.TypeTag[T]
): Unerase[T] = Unerase(v)
}
任何声明为Unerase[T]
而不是T
类型的变量都可以保证在运行时显示其完整声明的类型。不幸的是,这个例子在Scala 3中不再有效:
implicitly[TypeTag[Int]] // works in Scala 2
summon[Type[Int]] // doesn't work in Scala 3: No given instance of type quoted.Quotes was found for parameter x$1 ...
是否有一种机制可以用来实现完全减轻类型擦除的相同机制?
1条答案
按热度按时间qco9c6ql1#
您是否在寻找类似下面的内容(使用我在Is there a simple Scala 3 example of how to use
quoted.Type
as replacement forTypeTag
?中使用的方法)?