如何通过 Scala 反射访问默认参数值?

2024-03-01

假设我有一堂课:

case class Foo(id: Int, name: String, note: Option[String] = None)

自动生成的伴生对象中的构造函数和 apply 方法都采用三个参数。通过反射查看时,第三个参数(注)被标记:

p.isParamWithDefault = true

另外,通过检查我可以找到在伴生对象中生成值的方法:

method <init>$default$3

and

method apply$default$3

两者还具有:

m.isParamWithDefault = true

但是,我既无法在 Notes 参数的 TermSymbol 上找到任何实际指向我获取默认值的正确方法的内容,也无法在上述 MethodSymbol 上找到任何指向该参数的 TermSymbol 的内容。

是否有直接的方法将参数的 TermSymbol 与生成其默认值的方法链接起来?或者我是否需要做一些复杂的事情,例如检查伴随对象上的方法名称?

我对这里的案例类构造函数示例和常规方法都感兴趣。


拼凑是有不同程度的。

示例代码位于这个答案 https://stackoverflow.com/a/13813000/1296806,粘贴在下面。

正如我所说,名称的形式在 4.6、6.6.1 的规范中。这不是临时的。For every parameter pi , j with a default argument a method named f $default$n is generated which computes the default argument expression.

缺乏访问和重构这些生成名称的结构化能力是一个已知问题(ML 上的当前线程)。

import reflect._
import scala.reflect.runtime.{ currentMirror => cm }
import scala.reflect.runtime.universe._

// case class instance with default args

// Persons entering this site must be 18 or older, so assume that
case class Person(name: String, age: Int = 18) {
  require(age >= 18)
}

object Test extends App {

  // Person may have some default args, or not.
  // normally, must Person(name = "Guy")
  // we will Person(null, 18)
  def newCase[A]()(implicit t: ClassTag[A]): A = {
    val claas = cm classSymbol t.runtimeClass
    val modul = claas.companionSymbol.asModule
    val im = cm reflect (cm reflectModule modul).instance
    defaut[A](im, "apply")
  }

  def defaut[A](im: InstanceMirror, name: String): A = {
    val at = newTermName(name)
    val ts = im.symbol.typeSignature
    val method = (ts member at).asMethod

    // either defarg or default val for type of p
    def valueFor(p: Symbol, i: Int): Any = {
      val defarg = ts member newTermName(s"$name$$default$$${i+1}")
      if (defarg != NoSymbol) {
        println(s"default $defarg")
        (im reflectMethod defarg.asMethod)()
      } else {
        println(s"def val for $p")
        p.typeSignature match {
          case t if t =:= typeOf[String] => null
          case t if t =:= typeOf[Int]    => 0
          case x                         => throw new IllegalArgumentException(x.toString)
        }
      }
    }
    val args = (for (ps <- method.paramss; p <- ps) yield p).zipWithIndex map (p => valueFor(p._1,p._2))
    (im reflectMethod method)(args: _*).asInstanceOf[A]
  }

  assert(Person(name = null) == newCase[Person]())
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过 Scala 反射访问默认参数值? 的相关文章

随机推荐

  • .NET 中预抖动程序集的优点和缺点是什么?

    NET 中预抖动程序集的优点和缺点是什么 我听说预抖动可以提高性能 什么时候应该预抖动 什么时候不应该预抖动 预编译 或预编译将提高性能 启动时 因为您将跳过该步骤 每次应用程序及其库加载时 NET JIT 的原因是 它可以在许多平台和架构
  • 有没有办法禁用 ExtJS 4 中的树视图节点

    我的目的是禁用西部地区树视图的某些节点 下面的代码片段显示了这一点 root expanded true id treeview1 children text Make Copy leaf true id HS1 disabled true
  • 使用构建器模式时,我应该按值还是可变引用获取“self”?

    到目前为止 我在官方 Rust 代码和其他包中看到了两种构建器模式 impl DataBuilder pub fn new gt DataBuilder pub fn arg1 mut self arg1 Arg1Type gt mut B
  • Sphinx automodule:如何引用同一模块中的类?

    我正在尝试使用狮身人面像autodoc http www sphinx doc org en master usage extensions autodoc html扩展 特别是automodule指令自动为我正在开发的 django 应用
  • Vuex:跳过操作并直接从组件提交突变

    在 vue js 应用程序中 使用 vuex 作为状态管理存储 我只需更改 vuex 中属性的值 为此 我可以采用两种方法 派遣action方法 这将进一步提交mutation 最终会改变状态 第二种方法是提交mutation直接来自组件
  • 推荐工作流应用程序的设计模式[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在开发一个应用程序 用户可以在其中执行任务 工作流程 每个任务都由要执行的操作队列组成 我希望能够在工作流程启动后获得用户输入 Exampl
  • 使用jsoup登录网站

    On 这个网站 http kortladdning3 chalmerskonferens se 你可以输入你的学生卡号 然后就会显示该卡上还剩多少钱 我想使用JSOUP获取信息 这是我当前的代码 但它不起作用 String url http
  • ASP.NET MVC 2 中的 httppost、httpput 等属性如何工作?

    在 ASP NET MVC 2 中 引入了一些新的操作筛选器属性 作为 ASP NET MVC 1 中属性的 简写 例如 应用HttpPostAttribute与申请做同样的事情 AcceptVerbs HttpVerbs Post 到一个
  • 如何使用正则表达式按空格分割字符串并忽略前导和尾随空格到单词数组中?

    我通常在 JavaScript 中使用以下代码来按空格分割字符串 The quick brown fox jumps over the lazy dog split s The quick brown fox jumps over the
  • AWS Rekognition 检测标签无效图像编码错误

    我正在使用 boto3 调用识别的检测标签方法 该方法将图像 以 Base64 编码字节的形式 作为输入 但是我不断收到 InvalidImageFormatException 并且我不明白为什么 我已阅读文档并查看了一些示例 但我真的不明
  • Intellij 打开文件资源(忽略目标文件夹)

    当我使用 command shift o 命令时 我会收到以下弹出窗口 问题是在 Java EE 应用程序中将会出现目标中的重复项文件夹 有时我开始编辑错误的文件 我不想列出它们 请参阅图片 有没有办法排除文件夹 另外 还有一点 有时 in
  • 如何使用 Python 的 timeit 对代码段进行计时以测试性能?

    我有一个 python 脚本 它可以正常工作 但我需要编写执行时间 我已经用谷歌搜索过我应该使用timeit https docs python org 2 library timeit html但我似乎无法让它发挥作用 我的 Python
  • `a

    我很好奇我是否可以使用这个a
  • Java中修饰符关键字顺序

    每次我用Java编写一个方法时 关键字的数量都多于public void 每次我都会用另一种方式写 有时 static public void 有时 public static void etc 这些关键字的最佳顺序 最佳实践 是什么 ab
  • 创建错误消息 Delphi 7

    好的 我目前是一名 11 年级的学生 正在学习 IT 我正在尝试完成一项实际作业 但遇到了一些问题 我使用的教科书没有告诉我如何在用户未在 RichEdit 中输入数据时创建错误消息 谁能建议我如何做到这一点 感谢您抽出时间提供帮助 这是引
  • UISlider 在停止更改值后评估结果

    我有一个连续的 UI 滑块 我在值发生变化时获取该值 并使用它来计算放入文本字 段的值 我将值更改出口链接到执行计算并且工作正常的方法 但我还想要一种在用户抬起滑块后触发的方法 该方法有效地对最终设置值进行一次评估 我尝试连接 did en
  • 如何修复 DefaultKotlinSourceSetKt 的初始化错误?

    通过项目构建 或简单的 Gradle 同步 我遇到以下错误 导致 java lang NoClassDefFoundError 无法初始化类 org jetbrains kotlin gradle plugin sources Defaul
  • Roslyn .rsp 文件中的引用

    我在 CSharpInteractive rsp 中看到您可以使用 r 添加对 GAC 中 DLL 的引用 如何添加对自己的 DLL 的引用 我尝试了System Reflection Assembly LoadFrom 它没有失败 但不起
  • linq to sql ExecuteQuery() 作为 IQueryable

    ExecuteQuery 方法返回 IEnumerable 但有没有办法让它返回 IQueryable 嗯 你可以打电话AsQueryable 但它不会有任何好处 问题是当你使用ExecuteQuery 查询不是可组合的因为 LINQ to
  • 如何通过 Scala 反射访问默认参数值?

    假设我有一堂课 case class Foo id Int name String note Option String None 自动生成的伴生对象中的构造函数和 apply 方法都采用三个参数 通过反射查看时 第三个参数 注 被标记 p