2013-06-11 65 views
2

我目前無法將自己的頭圍繞Scala的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) 
      ... 
     } 
    } 
} 

與Scala的預定義類型匹配的模式正在工作。然而,我沒有設法檢查提供的泛型參數是否繼承我的特定特徵,並稍後檢索T後面的實際類的伴隨對象。嘗試一個簡單的typeOf[MyTrait[_, T]]正在被編譯器拒絕,告訴我沒有TypeTag可用於MyTag。我如何創建它?

此外,特質的令人討厭的通用簽名MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]]正在加劇整個事情。

除了一些有用的想法來解決這個問題,我非常感謝任何進一步的閱讀鏈接(我已閱讀所有關於這一點雖然)。

回答

2

使用以下方法來測試,如果它是一個對象(從this question):

typeOf[Test] <:< typeOf[Singleton] 

可以使用存在的類型讓你的特點的TypeTag

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

這工作,如果你在範圍內具有TypeTag[T]並且綁定如下:

T <: Entity[_,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 

然而,這不會工作你的情況,因爲T沒有正確界定。因此你必須對此進行測試(在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

@泰格似乎我們已經越過了彼此:P這也引起了我的關注。我添加了另一節。 – gzm0