如何从表示字段的给定String值中提取案例类字段的值。
例如:
case class Person(name: String, age: Int)
val a = Person("test",10)
现在这里给出了一个字符串name
或age
我想从变量a
中提取值。我该怎么做呢?我知道这可以用反射完成,但我不确定如何?
答案 0 :(得分:7)
使用无形镜片可以实现您所寻求的目标。这也将在编译时而不是运行时将字段实际存在于案例类中的约束:
import shapeless._
case class Person(name: String, age: Int)
val nameLens = lens[Person] >> 'name
val p = Person("myName", 25)
nameLens.get(p)
收率:
res0: String = myName
如果您尝试提取非现有字段,则会出现编译时错误,这是一个更强大的保证:
import shapeless._
case class Person(name: String, age: Int)
val nonExistingLens = lens[Person] >> 'bla
val p = Person("myName", 25)
nonExistingLens.get(p)
编译器大叫:
Error:(5, 44) could not find implicit value for parameter mkLens: shapeless.MkFieldLens[Person,Symbol with shapeless.tag.Tagged[String("bla")]]
val nonExistingLens = lens[Person] >> 'bla
答案 1 :(得分:1)
并不确切地知道你的想法,但是match
语句可以做到,对于Person
案例类的更改,它不是非常通用或可扩展的,但它确实如此满足不使用反射的基本要求:
scala> val a = Person("test",10)
a: Person = Person(test,10)
scala> def extract(p: Person, fieldName: String) = {
| fieldName match {
| case "name" => p.name
| case "age" => p.age
| }
| }
extract: (p: Person, fieldName: String)Any
scala> extract(a, "name")
res1: Any = test
scala> extract(a, "age")
res2: Any = 10
scala> extract(a, "name####")
scala.MatchError: name#### (of class java.lang.String)
at .extract(<console>:14)
... 32 elided
根据评论更新:
scala> case class Person(name: String, age: Int)
defined class Person
scala> val a = Person("test",10)
a: Person = Person(test,10)
scala> def extract(p: Person, fieldName: String) = {
| fieldName match {
| case "name" => Some(p.name)
| case "age" => Some(p.age)
| case _ => None
| }
| }
extract: (p: Person, fieldName: String)Option[Any]
scala> extract(a, "name")
res4: Option[Any] = Some(test)
scala> extract(a, "age")
res5: Option[Any] = Some(10)
scala> extract(a, "name####")
res6: Option[Any] = None
scala>
答案 2 :(得分:0)
我认为可以通过将case类转换为Map,然后按名称获取字段
def ccToMap(cc: AnyRef) =
(Map[String, Any]() /: cc.getClass.getDeclaredFields) {
(a, f) =>
f.setAccessible(true)
a + (f.getName -> f.get(cc))
}
用法
case class Person(name: String, age: Int)
val column = Person("me", 16)
println(ccToMap(column))
val name = ccToMap(column)["name"]