2012-08-13 1 views
3

런타임에 Scala 클래스의 모든 속성을 프로그래밍 방식으로 결정하고 싶습니다. 예를 들어, 다음 스칼라 클래스 나 메소드 name1, name3, name4name5A의 속성에 대한 게터 것을 결정하고 싶습니다 : 대부분의 작업 런타임시 Scala 클래스의 속성을 확인하는 방법은 무엇입니까?

class A(val name1: String, private val name2: String) { 
    val name3 = "" 
    var name4 = "" 
    def name5 = "" 
    def name6() = "" 
} 

는 자바의 리플렉션 API를 사용하여 수행 할 수 있습니다. 불행히도 name5name6()의 차이점을 감지 할 수 없었습니다. 따라서 ScalaSigParser를 사용하여 다음 시험판을 시작했지만 ScalaSig의 name5name6() 플래그는 불행히도 동일합니다. 당신은 두 가지 방법 만 info 값에 차이가 다음과 같은 출력에서 ​​볼 수 있듯이

def gettersOf(clazz: Class[_]) = { 
    for (ssig <- ScalaSigParser.parse(clazz)) 
    yield { 
    ssig.symbols.toList.collect{ 
     case m: MethodSymbol => m 
    }.filter(m => (m.symbolInfo.flags & 0xFFFFF) == 0x200) 
    } 
} 

gettersOf(classOf[A]).get.foreach{m => 
    println(m.name + ": " + m) 
} 

하기 :

name1: MethodSymbol(name1, owner=0, flags=28400200, info=22 ,None) 
<init>: MethodSymbol(<init>, owner=0, flags=200, info=38 ,None) 
name3: MethodSymbol(name3, owner=0, flags=8400200, info=45 ,None) 
name4: MethodSymbol(name4, owner=0, flags=8000200, info=45 ,None) 
name4_$eq: MethodSymbol(name4_$eq, owner=0, flags=8000200, info=54 ,None) 
name5: MethodSymbol(name5, owner=0, flags=200, info=45 ,None) 
name6: MethodSymbol(name6, owner=0, flags=200, info=66 ,None) 

그러나, info 정적 상수를 반환하지 않는 것 여기 내 코드입니다.

  • name3
      , name4name5이 같은 info
    • name6name5 항상 다른이에게 항상 가지고 : 당신이 클래스에 다른 방법을 추가 할 경우 일부 안정성있을 것 같습니다 동안 name6info 값이 변경됩니다 info

    사람은 info의 의미를 알고 있나요 하나는 확실히 그것이 방법의 종류를 결정하는 데 사용할 수있는 방법 ?

    관련 질문 :

  • +1

    직접적인 답변은 아니지만 스칼라 2에 대해 알고 계실 것입니다.10이 곧 돌아오고 새로운 반사 API가 생깁니 까? 당신은 저것을위한 공정표를 시도 할지도 모르다. –

    +0

    @BrianSmith : 힌트를 보내 주셔서 감사합니다. 실제로 Scala 2.10으로 바로 넘어 가고 싶습니다. 불행히도 대부분의 의존성은 2.10에서 아직 사용할 수 없습니다. –

    답변

    8

    향후 스칼라 2.10 리플렉션 API를 사용하는 것이 가장 좋습니다.

    여기 2.10.0-M6의 유형의 속성을 얻을 방법은 다음과 같습니다

    scala> import reflect.runtime.universe._ 
    import reflect.runtime.universe._ 
    
    scala> typeOf[A].members.view.filter{_.isValue}.filter{!_.isMethod}.toList 
    res0: List[reflect.runtime.universe.Symbol] = List(variable name4, value name3, value name2, value name1) 
    

    불행하게도 아직에 많은 읽을 거리가 아니다. 그래도 몇 가지 대답되는 질문이 있습니다. 예를 들어, this 질문은 당신에게 흥미로울 것입니다. Daniel Sobral의 블로그 게시물 this도 확인하십시오.

    +0

    와우. 이는 문제를 훨씬 단순화합니다. 모든 종속 라이브러리가 Scala 2.10과 호환되면이 솔루션으로 넘어갈 것입니다. –

    +0

    불행하게도, 런타임 리플렉션은 멀티 스레딩 환경에서 작동하지 않습니다. – jilen

    0

    나는 마침내 해결책을 발견했다. 우리가 name6없이 숨겨진 <init> 방법없이 원하는 결과를 얻을 결국

    def gettersOf(clazz: Class[_]) = { 
        for (ssig <- ScalaSigParser.parse(clazz)) 
        yield { 
        ssig.symbols.toList.collect { 
         case m: MethodSymbol => m 
        }.filter(m => (m.symbolInfo.flags & 0xFFFFF) == 0x200 && m.infoType.isInstanceOf[NullaryMethodType]) 
        } 
    } 
    

    대신 원시 info 값을 사용하는 사람은 괄호를 가진 모든 방법에 대한 NullaryMethodType를 반환하는 것보다 정보 infoType을 사용할 수 있습니다 :

    name1: MethodSymbol(name1, owner=0, flags=28400200, info=22 ,None) 
    name3: MethodSymbol(name3, owner=0, flags=8400200, info=45 ,None) 
    name4: MethodSymbol(name4, owner=0, flags=8000200, info=45 ,None) 
    name5: MethodSymbol(name5, owner=0, flags=200, info=45 ,None) 
    
    3
    import reflect.runtime.universe._ 
    typeOf[A].members map (m => m -> m.typeSignature) collect { 
        case (m, nm: NullaryMethodType) => m 
    }