2013-06-11 7 views
2

현재 스칼라의 TypeTag 리플렉션 API로 머리를 감쌀 수 없습니다. 웹상에서 발견 할 수있는 정보가 거의 없으며 모든 시행 착오 시도는 어디에도 없습니다.제네릭 형식 인수의 패턴 일치 방법은 무엇입니까?

def doStuff[T: TypeTag](param: String): SomeStuff[E] = 
{ 
    val t = typeOf[T] 

    if(<t extends one specific Trait from my application and is an object>) 
    { 
     <retrieve that companion object and return one of its values> 
    } 
    else 
    { 
     t match 
     { 
      case x if x =:= typeOf[String] => doOtherStuff[String](param) 
      case x if x =:= typeOf[Int] => doOtherStuff[Int](param) 
      ... 
     } 
    } 
} 

스칼라의 사전 정의 된 유형과 일치하는 패턴이 작동합니다. 그러나 제공된 일반 인수가 특정 특성을 상속 받았는지 확인한 다음 나중에 T 뒤에 실제 클래스의 동반 개체를 검색했는지 확인하지 못했습니다. 컴파일러는 TypeTag를 MyTag에 사용할 수 없다고 말하면서 곧바로 typeOf[MyTrait[_, T]]으로 시도하고 있습니다. 어떻게 만들 수 있습니까?

또한 특성의 지저분한 일반적인 서명 MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]]은 모든 것을 악화시키고 있습니다.

이 문제를 해결하는 데 도움이되는 아이디어 외에도 나는 더 읽기 링크 (나는 모두를 읽었습니다.)를 매우 고맙게 생각합니다.

답변

2

사용은 (this question에서) 객체 인 경우 테스트하기 위해 다음과 같은 :이 경우 작동

typeOf[MyTrait[M, T] forSome { type M <: MyTrait[M, T] }] 

: 당신은 당신의 특성의 TypeTag을 얻기 위해 존재 형식을 사용할 수 있습니다

typeOf[Test] <:< typeOf[Singleton] 

가 범위는 TypeTag[T]이며 다음과 같이 구속됩니다.

T <: Entity[_,T] 

최소 예 : T이 제대로 경계하지 않기 때문에

trait Entity[M, E] 
trait MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]] 

class MyEnt extends Entity[Test, MyEnt] 
class Test extends MyTrait[Test, MyEnt] 

def getType[T <: Entity[_, T] : TypeTag] = 
    typeOf[MyTrait[M,T] forSome { type M <: MyTrait[M,T] }] 

typeOf[Test] <:< getType[MyEnt] 
//| res0: Boolean = true 

그러나, 이것은 귀하의 경우에는 작동하지 않습니다. 그러므로 당신은 이것 (어떤 도움을 받아 here에서 도움을 얻어)을 시험해야 할 것입니다 :

val mts = typeOf[MyTrait[_,_]].typeSymbol 

typeOf[Test].baseType(mts) match { 
    case TypeRef(_, _, List(_, t)) if t <:< typeOf[MyEnt] => true 
    case _ => false 
} 
+0

'T' 인자는 무한합니다. 그것은 'MyTrait'일 수도 있지만 'Int'일 수도 있습니다. 따라서 제네릭 경계가 일치하지 않으므로'getType' 메서드를 사용할 수 없습니다. 이걸 극복 할 방법이 있니? (나를 소개 해주셔서 'forSome'). – Taig

+0

@Taig 우리가 서로 교차 한 것처럼 보입니다 : P 이것 역시 내 관심사가되었습니다. 나는 다른 섹션을 추가했다. – gzm0