В Scala, в чем разница между Universe.TypeTag, TypeRef и Type?

Есть 3 разных класса, ограниченных вселенной: TypeTag, TypeRef и Type. Зачем нужны все 3? Если у меня есть только Type, как мне преобразовать его в TypeTag или TypeRef?

Например. Я получил общий супертип через функцию API отражения Scala:

val at = ...some TypeTag...
val bt = ...some TypeTag...

val tpe = ScalaReflection.universe.lub(List(at.tpe, bt.tpe))
ScalaReflection.universe.(tpe)

Как преобразовать его в TypeTag или TypeRef?


person tribbloid    schedule 04.06.2016    source источник


Ответы (1)


TypeRef является частным случаем Type:

abstract type TypeRef >: Null <: Universe.TypeRefApi with Universe.Type 

Вы можете проверить, является ли Type на самом деле TypeRef, с помощью сопоставления с образцом:

tpe match {
  case TypeRef(prefix, sym, args) =>
  // or alternately
  case typeRef: TypeRef =>
}

TypeTag[A] — это способ получить доступ к Type, который 1) работает для разных зеркал; 2) может быть сгенерирован компилятором автоматически из параметра типа (обратите внимание, что Type не является универсальным).

Чтобы преобразовать Type в TypeTag, из Как создать TypeTag вручную?:

import scala.reflect.runtime.universe._

def typeToTypeTag[T](
  tpe: Type,
  mirror: reflect.api.Mirror[reflect.runtime.universe.type]
): TypeTag[T] = {
  TypeTag(mirror, new reflect.api.TypeCreator {
    def apply[U <: reflect.api.Universe with Singleton](m: reflect.api.Mirror[U]) = {
      assert(m eq mirror, s"TypeTag[$tpe] defined in $mirror cannot be migrated to $m.")
      tpe.asInstanceOf[U#Type]
    }
  })
}
person Alexey Romanov    schedule 05.06.2016