在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,报告其发现并消失. 任何可以改进此解决方案的评论或解释“暗示”究竟如何做他们所做的事情(或者如果他们可以被删除)都是受欢迎的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
