You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala 3中如何在运行时保留对象声明类型以缓解类型擦除?

Scala 3中如何在运行时保留对象的声明类型以缓解类型擦除?

Scala 3完全可以实现类似Scala 2中保留运行时完整声明类型的机制,只是需要适配Scala 3全新的反射与编译时API——原来的TypeTag被拆分为scala.quoted.Type(负责携带完整编译时类型信息)和依赖Quotes上下文的获取方式,直接summon[Type[Int]]失败正是因为缺少编译时的Quotes上下文。

核心实现思路

利用Scala 3的inline方法与编译时宏能力,在编译阶段捕获完整的类型信息并绑定到包装对象上,无需依赖全局缓存(当然也可以根据需求保留缓存逻辑)。以下是适配Scala 3的Unerase实现:

import scala.collection.concurrent.TrieMap
import scala.quoted.*
import scala.language.implicitConversions

// 包装类,直接存储值与对应的完整类型信息
case class Unerase[T](self: T, private val typeRep: Type[T])

object Unerase {
  // 可选:如果需要复用类型信息可以保留全局缓存(和Scala 2示例逻辑对齐)
  private lazy val cache = TrieMap.empty[Int, Type[_]]

  // 通过inline方法在编译时捕获Type[T],依赖Quotes上下文
  inline def apply[T](value: T): Unerase[T] = ${ applyImpl[T]('value) }

  // 宏实现:在编译阶段获取Type[T]并构造Unerase实例
  private def applyImpl[T: Type](value: Expr[T])(using Quotes): Expr[Unerase[T]] = {
    val typeRep = Type[T]
    // 可选:将类型信息存入缓存
    cache += System.identityHashCode(value) -> typeRep
    '{ Unerase($value, ${ Expr(typeRep) }) }
  }

  // 获取包装对象的完整类型信息
  def getType[T](unerased: Unerase[T]): Type[T] = unerased.typeRep

  // 隐式包装:自动将任意值转换为Unerase实例,inline确保编译时捕获类型
  inline implicit def box[T](value: T): Unerase[T] = apply(value)

  // 隐式解包:自动将Unerase实例转换回原类型
  implicit def unbox[T](unerased: Unerase[T]): T = unerased.self
}

使用示例

// 自动隐式包装基础类型
val intVal: Unerase[Int] = 42
// 自动隐式包装带泛型的复杂类型
val strList: Unerase[List[String]] = List("foo", "bar")

// 获取并打印完整类型信息
println(Unerase.getType(intVal))       // 输出: Int
println(Unerase.getType(strList))      // 输出: List[String]

关键细节说明

  1. inline与Quotes上下文:inline方法允许在编译阶段访问Quotes上下文,从而获取Type[T]——这是Scala 3中获取完整编译时类型信息的核心方式,替代了Scala 2中TypeTag的隐式推导逻辑。
  2. 类型信息存储:示例中直接将Type[T]绑定到Unerase实例,避免了Scala 2示例中全局缓存可能带来的内存泄漏或哈希冲突问题;如果需要复用类型信息,也可以保留原有的全局缓存逻辑。
  3. 泛型类型保留:Type[T]会完整保留泛型参数信息(比如List[String]不会被擦除为List[_]),完全满足缓解类型擦除的需求。

额外扩展

如果需要对类型信息进行更复杂的反射操作(比如遍历泛型参数、获取注解等),可以结合Scala 3的scala.reflectAPI,将Type[T]转换为可操作的反射节点,实现类似Scala 2中TypeTag的所有功能。

内容的提问来源于stack exchange,提问作者tribbloid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:25:27