В этом посте:
Можно ли конвертировать TypeTag в манифест?
Указывается, что TypeTag можно конвертировать в манифест с помощью следующий код:
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]]
}
Не работает , как показано в следующем тестовом примере:
object TypeTag2Manifest {
class Example {
type T = Map[String, Int]
}
val example = new Example
}
class TypeTag2Manifest extends FunSpec {
import org.apache.spark.sql.catalyst.ScalaReflection.universe._
import TypeTag2Manifest._
it("can convert") {
val t1 = implicitly[TypeTag[example.T]]
val v1 = toManifest(t1)
val v2 = implicitly[Manifest[example.T]]
assert(v1 == v2)
}
}
Выход:
scala.collection.immutable.Map did not equal scala.collection.immutable.Map[java.lang.String, Int]
ScalaTestFailureLocation: com.tribbloids.spike.scala_spike.reflection.TypeTag2Manifest at (TypeTag2Manifest.scala:52)
Expected :scala.collection.immutable.Map[java.lang.String, Int]
Actual :scala.collection.immutable.Map
Очевидно, это указывает на то, что стирание типа мешало преобразованию, и TypeTag, несмотря на то, что был разработан, чтобы избежать стирания типа, может преобразовываться только в зависимый тип example.T
без получения правильных аргументов типа из базового типа Map[String, Int]
.
Так как же конвертировать TypeTag и Manifest друг в друга, которые не сосут?