В нашей библиотеке используются TypeTags, но теперь нам нужно взаимодействовать с другой библиотекой, которая требует Manifests. Есть ли простой способ создания манифеста из TypeTag?
Можно ли преобразовать TypeTag в манифест?
Ответ 1
gourlaysama anwer использует Class [_], поэтому аргументы типа стираются. Я придумал реализацию, которая сохраняет аргументы типа здесь: Как сохранить параметр типа во время преобразования TypeTag в Manifest?
Здесь код:
def toManifest[T:TypeTag]: Manifest[T] = {
val t = typeTag[T]
val mirror = t.mirror
def toManifestRec(t: Type): Manifest[_] = {
val clazz = ClassTag[T](mirror.runtimeClass(t)).runtimeClass
if (t.typeArgs.length == 1) {
val arg = toManifestRec(t.typeArgs.head)
ManifestFactory.classType(clazz, arg)
} else if (t.typeArgs.length > 1) {
val args = t.typeArgs.map(x => toManifestRec(x))
ManifestFactory.classType(clazz, args.head, args.tail: _*)
} else {
ManifestFactory.classType(clazz)
}
}
toManifestRec(t.tpe).asInstanceOf[Manifest[T]]
}
Ответ 2
Если вы попытаетесь наивно вызвать Manifest
, когда присутствует TypeTag
, компилятор даст вам подсказку относительно решения:
import reflect.runtime.universe._
import reflect.ClassTag
def test[A : TypeTag] = manifest[A]
error: to create a manifest here, it is necessary to interoperate with the type
tag `evidence$1` in scope.
however typetag -> manifest conversion requires a class tag for the corresponding
type to be present.
to proceed add a class tag to the type `A` (e.g. by introducing a context bound)
and recompile.
def test[A : TypeTag] = manifest[A]
^
Итак, если у вас есть ClassTag
в области видимости, компилятор сможет создать необходимый Manifest
. У вас есть два варианта:
-
Добавить второй контекст, связанный всюду
TypeTag
, как в:def test[A : TypeTag : ClassTag] = manifest[A] // this compiles
-
Или сначала преобразуйте
TypeTag
вClassTag
, затем попроситеManifest
:def test[A](implicit ev: TypeTag[A]) = { // typeTag to classTag implicit val cl = ClassTag[A]( ev.mirror.runtimeClass( ev.tpe ) ) // with an implicit classTag in scope, you can get a manifest manifest[A] }