如何访问访问案例类字段值来自字段的字符串名称

Sid*_*ant 7 scala case-class

如何从表示该字段的给定String值中提取案例类的字段值.

例如:

case class Person(name: String, age: Int)
val a = Person("test",10)
Run Code Online (Sandbox Code Playgroud)

现在这里给出一个字符串nameage我想从变量中提取值a.我该怎么做呢?我知道这可以用反射完成,但我不确定如何?

Yuv*_*kov 8

您正在寻找的是使用无形镜片.这也将在编译时而不是运行时将字段实际存在于案例类的约束:

import shapeless._

case class Person(name: String, age: Int)

val nameLens = lens[Person] >> 'name
val p = Person("myName", 25)

nameLens.get(p)
Run Code Online (Sandbox Code Playgroud)

产量:

res0: String = myName
Run Code Online (Sandbox Code Playgroud)

如果您尝试提取非现有字段,则会出现编译时错误,这是一个更强大的保证:

import shapeless._

case class Person(name: String, age: Int)

val nonExistingLens = lens[Person] >> 'bla
val p = Person("myName", 25)

nonExistingLens.get(p)
Run Code Online (Sandbox Code Playgroud)

编译器大叫:

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
Run Code Online (Sandbox Code Playgroud)

  • 我们可以使用 `String` 而不是 `Symbol` 像 `'bla` 吗? (3认同)
  • @pleasehalp您不能只使用任何任意字符串变量,因为需要在编译时知道符号。 (3认同)

Yan*_*eve 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
Run Code Online (Sandbox Code Playgroud)

根据评论更新:

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>
Run Code Online (Sandbox Code Playgroud)

  • 然后也许可以检查无形状:[无形状镜片](https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#boilerplate-free-lenses-for- Arbitrary-case-classes) (2认同)