在Scala中,如何以编程方式确定案例类的字段名称?
在
Scala中,假设我有一个这样的案例类:
case class Sample(myInt: Int,myString: String) 有没有办法让我获得Seq [(String,Class [_])],或者更好的是,Seq [(String,Manifest)],描述case类的参数? 解决方法
这是我(两年后).这是使用Scala反射的不同的不同解决方案.它的灵感来自
blog post,它本身的灵感来自于
Stack Overflow exchange.下面的解决方案专门针对上面原始海报的问题.
在一个编译单元(REPL:paste或编译的JAR)中,包括scala-reflect作为依赖项并编译以下内容(在Scala 2.11中测试,可能在Scala 2.10中有效): import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context object CaseClassFieldsExtractor { implicit def makeExtractor[T]: CaseClassFieldsExtractor[T] = macro makeExtractorImpl[T] def makeExtractorImpl[T: c.WeakTypeTag](c: Context): c.Expr[CaseClassFieldsExtractor[T]] = { import c.universe._ val tpe = weakTypeOf[T] val fields = tpe.decls.collectFirst { case m: MethodSymbol if (m.isPrimaryConstructor) => m }.get.paramLists.head val extractParams = fields.map { field => val name = field.asTerm.name val fieldName = name.decodedName.toString val NullaryMethodType(fieldType) = tpe.decl(name).typeSignature q"$fieldName -> ${fieldType.toString}" } c.Expr[CaseClassFieldsExtractor[T]](q""" new CaseClassFieldsExtractor[$tpe] { def get = Map(..$extractParams) } """) } } trait CaseClassFieldsExtractor[T] { def get: Map[String,String] } def caseClassFields[T : CaseClassFieldsExtractor] = implicitly[CaseClassFieldsExtractor[T]].get 在另一个编译单元(REPL中的下一行或使用前一个作为依赖项编译的代码)中,使用它如下: scala> case class Something(x: Int,y: Double,z: String) defined class Something scala> caseClassFields[Something] res0: Map[String,String] = Map(x -> Int,y -> Double,z -> String) 这似乎有点矫枉过正,但我??还是没能把它变得更短.这是它的作用: > caseClassFields函数创建一个隐式存在的中间CaseClassFieldsExtractor,报告其发现并消失. 任何可以改进此解决方案的评论或解释“暗示”究竟如何做他们所做的事情(或者如果他们可以被删除)都是受欢迎的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |