2016-03-02 3 views
1

Я понимаю, что TypeTags позволяет нам восстанавливать типы во время выполнения. Тем не менее, я не могу сделать это при использовании коллекции параметризированный с TypeTag[_]:Как восстановить тип во время выполнения с помощью typetags?

Вот моя первая попытка:

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

Смежные вопросы