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

Scala 3 quotes如何获取case class字段的默认值

访问case class字段默认值的可行方案

当前版本的TASTy/Quotes API完全支持获取case class字段默认值,之前的调用方式未命中目标,核心原因是Scala 3的默认值实现机制:参数默认值不会直接存储在字段符号上,而是由编译器在类的伴生对象中生成专属合成方法存储。

核心实现逻辑

Scala编译器为构造方法中每一个带默认值的参数,都会在对应伴生对象中生成名为<init>$default$<序号>的合成方法:

  • 序号从1开始计数,对应参数在主构造方法参数列表中的位置
  • 调用该合成方法即可直接返回对应参数的默认值
  • 没有配置默认值的参数不会生成对应合成方法

以定义的case class User(name: String = "Shayan")为例,编译器会自动在User的伴生对象中生成<init>$default$1方法,调用该方法就会返回字符串"Shayan"。

可运行实现代码

import scala.quoted.*

inline def listCaseClassDefaults[T]: Map[String, Any] = ${ listCaseClassDefaultsImpl[T] }

private def listCaseClassDefaultsImpl[T: Type](using Quotes): Expr[Map[String, Any]] =
  import quotes.reflect.*
  val typeRepr = TypeRepr.of[T]
  val classSymbol = typeRepr.classSymbol.getOrElse(
    report.errorAndThrow("Target type is not a concrete class")
  )
  // 获取主构造方法、伴生对象符号
  val primaryCtor = classSymbol.primaryConstructor
  val companionSymbol = typeRepr.typeSymbol.companionModule

  val defaultEntryExprs = primaryCtor.paramSymss.flatten.zipWithIndex.flatMap { (param, index) =>
    val targetMethodName = s"$$init$$default$$${index + 1}"
    // 查找对应默认值合成方法
    companionSymbol.declaredMethod(targetMethodName).headOption.map { defaultMethod =>
      val defaultExpr = Ref(companionSymbol).select(defaultMethod).asExprOf[Any]
      Expr(param.name -> defaultExpr)
    }
  }

  Expr.ofList(defaultEntryExprs).asExprOf[Map[String, Any]]

// 测试验证
case class User(name: String = "Shayan", age: Int = 18, email: String)
@main def runTest(): Unit =
  println(listCaseClassDefaults[User])
  // 输出结果: Map(name -> Shayan, age -> 18)

之前调用方式无效的原因

  • caseFields接口仅返回字段的基础符号信息,包含名称、类型、可见性等属性,默认值属于构造调用阶段的fallback逻辑,不属于字段本身的元数据,因此不会挂载在caseFields返回的符号对象上
  • Symbol.tree是官方明确标注的不稳定内部接口,本身就不保证返回完整的类定义结构,依赖该接口获取信息会出现随机的字段缺失,不适合在宏逻辑中使用

额外注意点

  • 如果要获取case class伴生对象apply方法的参数默认值,对应的合成方法名规则为apply$default$<序号>,查找逻辑和构造方法默认值完全一致
  • 多参数列表的场景下,遍历所有参数列表的参数后按全局顺序计数即可,不需要单独处理参数列表的分层
  • 合成方法的查找范围要限定在伴生对象的成员内,不要去类本身的成员里查找,类本身不会持有这些默认值方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:01:03