假设我有一堂课:
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(使用前将#替换为@)