2016-03-02 44 views
1

我的理解是TypeTags可以讓我們在運行時恢復類型。但是,我使用集合參數與TypeTag[_]時,我不能這樣做:如何使用類型標籤在運行時恢復類型?

這是我第一次嘗試:

import scala.reflect.runtime.universe._ 
import scala.collection.mutable 

type TaggedVal = Tuple2[TypeTag[_], Any] 
val tagMap: Map[Int, TaggedVal] = Map(
    0 -> (typeTag[Int], 12345), 
    1 -> (typeTag[String], "abcde") 
) 


def get[T](key: Int)(implicit tag: TypeTag[T]) = tagMap.get(key) match { 
    case Some((t, v)) => Some(v.asInstanceOf[T]) 
    case _ => None 
} 

implicit val zeroTag = tagMap(0)._1 
val zero = get(0).get 
val testing: Int = zero 

這將導致未能取回存儲類型:

Error:(18, 26) type mismatch; 
found : Any 
required: Int 
lazy val testing: Int = zero 
        ^

第二個類似的嘗試如下,但它導致匹配錯誤:

type TypedVal = Tuple2[Type, Any] 
val tagMap: mutable.Map[Int, TypedVal] = mutable.Map() 

def put[T: TypeTag](key: Int, value: T) = tagMap.put(key, (typeOf[T], value)) 

def get[T: TypeTag](key: Int) = tagMap.get(key).get match { 
    case tv: TypedVal if tv._1 =:= typeOf[T] => Some(tv._2.asInstanceOf[T]) 
} 

put(0, (typeOf[Int], 12345)) 
put(1, (typeOf[String], "abcde")) 
val zero = get(0).get 

有沒有合理的方法可以做到這一點?

參考:How save a TypeTag and then use it later to reattach the type to an Any (Scala 2.10)

回答

1

您需要的類型參數自己提供給get,否則不能正常工作。你實質上是在編譯時詢問這個類型,而在運行時只知道它的類型。

type TaggedVal = (TypeTag[_], Any) 

val tagMap: Map[Int, TaggedVal] = Map(
    0 -> (typeTag[Int], 12345), 
    1 -> (typeTag[String], "abcde") 
) 

def get[T](key: Int)(implicit tag: TypeTag[T]): Option[T] = tagMap.get(key) match { 
    case Some((t, v)) if t.tpe =:= typeOf[T] => Some(v.asInstanceOf[T]) 
    case _ => None 
} 

scala> get[String](1) 
res31: Option[String] = Some(abcde) 

scala> get[Int](1) 
res32: Option[Int] = None 

類似以下(不強制類型參數),但是,不能正常工作,因爲那是返回(通過鑄造)類型是在運行時只知道。無法推斷爲i作爲Int

val i = get(0).get 
val j: Int = i 
+0

內心深處,我想我知道是這樣,但我想確定 - 謝謝。我結束了在案例類和類型類中包裝我所需要的東西,以試圖理解它 - 似乎到目前爲止工作。 – bbarker