2017-08-07 31 views
5

Jak wyodrębnić wartość pola klasy case z danej wartości String reprezentującej pole.Jak uzyskać dostęp do pola klasy Case Wartość z nazwy String pola

Na przykład:

case class Person(name: String, age: Int) 
val a = Person("test",10) 

Teraz tutaj podany ciąg name lub age chcę wyodrębnić wartość od zmiennej a. Jak mam to zrobic? Wiem, że można to zrobić za pomocą refleksji, ale nie jestem do końca pewny w jaki sposób?

+0

I chcę mieć możliwość bezpiecznego wyodrębnienia wartości. Znaczy to, że jeśli nie ma tam pola, powinienem dostać Nic albo coś takiego. – Sidhant

+0

W jakim przypadku przypadek nie powinien mieć "nazwy" lub "wieku"? –

Odpowiedz

0

Nie wiem dokładnie, co miałeś na myśli, ale zrobiłoby to oświadczenie match, nie jest ono bardzo ogólne ani rozszerzalne w odniesieniu do zmian w klasie przypadku Person, ale spełnia podstawowe wymagania dotyczące niewykorzystywania refleksji:

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 

UPDATE zgodnie komentarza:

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> 
+0

Tak, ale muszę napisać opakowanie. Chcę to osiągnąć w czasie wykonywania bez ręcznego pisania funkcji opakowania. – Sidhant

+1

następnie prawdopodobnie nieformalne: [bezkształtne soczewki] (https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#boilerplate-free-lenses-for-arbitrary-case-classes) – Yaneeve

3

Co czego szukasz, możesz osiągnąć za pomocą bezkształtnych soczewek. Będzie to również umieścić ograniczenie, że pole faktycznie istnieje w klasie przypadku w czasie kompilacji zamiast uruchomić czas:

import shapeless._ 

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

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

nameLens.get(p) 

Wynik:

res0: String = myName 

Jeśli spróbujesz wyodrębnić nieistniejących pole, dostać czasie kompilacji błąd, który jest znacznie silniejszy gwarancja:

import shapeless._ 

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

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

nonExistingLens.get(nonExistingLens) 

Compiler krzyczy:

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

Miło, jak zwykle. Mieć uprowadzenie. – slouc