2013-12-09 5 views
2

Matt R's question의 후속 조치로서 스칼라 2.10은 상당한 시간 동안 사용되지 않았으므로 케이스 클래스의 필드와 값을 추출하는 가장 좋은 방법은 무엇입니까?리플렉션을 통해 케이스 클래스의 매개 변수 얻기

[(red, 1),(green, 3),(blue, "isBlue")] 

:

case class Colour(red: Int, green: Int, blue: String) { 
    val other: Int = 42 
} 

val RBG = Colour(1,3,"isBlue") 

내가 필드는이 같은 튜플 값으로 생성자에서 선언했을 목록 (또는 배열 또는 그 문제에 대한 모든 반복자를) 싶어 : 비슷한 예를 촬영 나는 같은 문제에 관해 그물에 많은 예제가 있다는 것을 알고 있지만, 내가 말했듯이, 필요한 정보를 추출하는 가장 이상적인 방법이 무엇인지 알고 싶었다.

+0

것은 당신이 제품 방법을 사용할 수 있어야합니다 : 별도로 각 단계를 거치지 않고, 여기에 해결책이 전부입니다 (매개 변수의 값을 추출하는 메커니즘에 대한 val value = 라인 참조) zipwithindex와 함께 productIterator. –

답변

4

스칼라 2.10 리플렉션을 사용하는 경우, this answer은 필요한 것의 절반입니다. . 그것은 당신이 경우 클래스의 방법 기호를 줄 것이다, 그래서 당신은 인수의 순서와 이름을 알고

import scala.reflect.runtime.{universe => ru} 
import ru._ 

def getCaseMethods[T: TypeTag] = typeOf[T].members.collect { 
    case m: MethodSymbol if m.isCaseAccessor => m 
}.toList 

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

getCaseMethods[Person] // -> List(value age, value name) 

당신은 해당 메소드 이름을 얻기 위해 이러한 방법에 .name.toString를 호출 할 수 있습니다.

다음 단계는 주어진 인스턴스에서 이러한 메소드를 호출하는 것입니다.

val p = Person("foo", 33) 
val pr = rm.reflect(p) 

는 그런 다음 reflectMethod를 사용하여 각 방법 pr에 반영 apply를 통해 그것을 실행할 수 있습니다 당신은 그럼 당신은 "거울"실제 인스턴스 수

val rm = runtimeMirror(getClass.getClassLoader) 

에 대한 런타임 거울이 필요합니다. 경우 클래스가 제품 특성을 구현할

def caseMap[T: TypeTag: reflect.ClassTag](instance: T): List[(String, Any)] = { 
    val im = rm.reflect(instance) 
    typeOf[T].members.collect { 
    case m: MethodSymbol if m.isCaseAccessor => 
     val name = m.name.toString 
     val value = im.reflectMethod(m).apply() 
     (name, value) 
    } (collection.breakOut) 
} 

caseMap(p) // -> List(age -> 33, name -> foo)