加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-16 09:17:10 所属栏目:安全 来源:网络整理
导读:假设我有一个班: case class Foo(id: Int,name: String,note: Option[String] = None) 自动生成的伴随对象中的构造函数和应用方法都有三个参数.通过反射查看时,第三个参数(注)被标记: p.isParamWithDefault = true 此外,通过检查,我可以找到在伴随对象中生
假设我有一个班:

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

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

p.isParamWithDefault = true

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

method <init>$default$3

method apply$default$3

哪个都有:

m.isParamWithDefault = true

但是,我不能在TermSymbol上找到任何关于notes参数的任何东西,实际上我使用正确的方法获取默认值,也不会在上述MethodSymbols上返回参数的TermSymbol.

有一个直接的方式来连接TermSymbol的参数与生成其默认值的方法?或者我需要做一些kludgey的事情,例如检查伴侣对象上方法的名称?

我对这个对于这里的case类构造函数示例和常规方法感兴趣.

解决方法

有泥度的程度.

示例代码为this answer,粘贴在下面.

所以正如我所说,这个名字的格式在4.6,6.6.1中.这不是特别的.对于每个参数pi,j使用默认参数生成一个名为f $default $n的方法,它计算默认参数表达式.

缺少访问和重构这些生成的名称的结构化能力是一个已知的问题(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]())
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读