How do I access default parameter values via Scala reflection?

前端 未结 3 990
不思量自难忘°
不思量自难忘° 2020-12-03 01:40

Let\'s say a I have a class:

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

Both the constructor and the apply method i

3条回答
  •  [愿得一人]
    2020-12-03 02:14

    For case when you only have Type of Foo:

    % scala
    Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 15-loom).
    
    scala> :paste
    
    import scala.reflect.runtime.currentMirror
    import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe.definitions._
    
    def defaults(tpe: Type): Seq[(Int, Any)] = {
      tpe.typeSymbol.asClass.primaryConstructor.asMethod.paramLists.flatten.
        zipWithIndex.flatMap{ case (x, i) =>
        if (x.asTerm.isParamWithDefault) {
          val m = currentMirror
          val im = m.reflect(
            m.reflectModule(tpe.typeSymbol.asClass.companion.asModule).instance
          )
          val method = tpe.companion.decl(
            TermName("apply$default$"+(i+1).toString)
          ).asMethod
          val v = im.reflectMethod(method)()
          Some(i -> v)
        } else None
      }
    }
    
    scala> case class Foo(id: Int, name: String, note: Option[String] = None)
    
    scala> defaults(typeOf[Foo])
    res0: Seq[(Int, Any)] = List((2,None))
    

    The same way you can call any method on companion object.

    Documentation about Mirrors contains example how to invoke method on class.

提交回复
热议问题