2013-12-09 3 views
0

나는 여러 가지 사례 클래스로 확장 된 '계약'이라는 어머니 특성을 가지고 있는데, 그 중 하나 인 '축척'이 있습니다. 나는 그것들이 어떤 종류의 객체인지에 기초하여 그러한 사례 클래스들 중 하나의 객체를 취하고 어떤 행동을 취하는 것과 같은 일반적인 함수를 만들기 위해 노력하고있다. 다음은 부분 코드입니다.일반 함수 만들기 및 TypeOf 사용하기

def getType[T: TypeTag](obj: T) = typeOf[T] 

def makeXMLElem[T <: Contract](contract: T): String = { 
     println(getType(contract)) 
     val symb = getType(contract).declaration(newTermName(name)).asTerm 
     val instanceMirror = runtimeMirror(contract.getClass.getClassLoader).reflect(contract) 
     val symbMirror = instanceMirror.reflectField(symb) 
     val symbValue = symbMirror.get 
     ....... 

이제 '크기'를 전달하고 형식을 확인하려고합니다. getType 함수는 'scale'이 아닌 'contract'이되도록 형식을 반환합니다. 당신이, 내가 문 사용하는 경우 클래스 '규모'의 매개 변수에 액세스하려고 이해할 수 있듯이 : 이후

case class scale(amount:Int, currency:String) 

의 :

val symb = getType(contract).declaration(newTermName(name)).asTerm 

경우 클래스 '규모'를 다음 서명이 자체가 잘못 추출되는 입력 값 'SYMB은'어떤 가치를 부여하지 않고, 나는 다음과 같은 런타임 오류 얻을 : 손실 오없이

Caused by: scala.ScalaReflectionException: <none> is not a term 

가 어떻게 기능 makeXMLElem가 더 일반적인 만들 수 있습니다 '규모'의 서명 또는 그 문제에 대해 '계약'을 확장하는 클래스에 관한 정보?

답변

2

getType의 정의에서 알 수 있듯이 typeOf[T] 함수는 실제로 값 obj을 전혀 신경 쓰지 않습니다. 컴파일 시간이 일 때 일뿐입니다. T의 대표적인 표현을 제공합니다. 따라서 trait Foo; trait Bar extends Foo; getType[Foo](new Bar {}) 인 경우 Foo이 아닌 유형 정보가 Bar이됩니다. 구체화 된 제네릭의 요점은 컴파일 타임에 필요한 정보를 보존하는 것입니다.

이 솔루션은 this answer에있다 : 당신은 getClass를 통해 contract실행시 클래스를 사용하고 그 결과를 반영해야한다.

def getType[T](clazz: Class[T])(implicit rm: ru.Mirror) = 
    rm.classSymbol(clazz).toType 

val symb = getType(contract.getClass) 

따라서 메서드 서명을 def makeXMLElem(contract: Constract)으로 단순화 할 수 있습니다.


예 :

import reflect.runtime.{universe => ru} 
import ru._ 
implicit val rm = runtimeMirror(getClass.getClassLoader) 

trait Foo; case class Bar(baz: Int) extends Foo 

val b: Foo = Bar(33) 
b.getClass // Bar! 

val symb   = getType(b.getClass).declaration(newTermName("baz")).asTerm 
val instanceMirror = rm.reflect(b) 
val symbMirror  = instanceMirror.reflectField(symb) 
symbMirror.get // 33 !