Unsere Bibliothek verwendet TypeTags, aber jetzt müssen wir mit einer anderen Bibliothek interagieren, die Manifests erfordert. Gibt es eine einfache Möglichkeit, ein Manifest aus einem TypeTag zu erstellen?Kann ein TypeTag in ein Manifest konvertiert werden?
10
A
Antwort
3
gourlaysamas anwer verwendet Class [_], also ty Die Argumente werden gelöscht. Ich habe mit einer Implementierung kommen, die die Typargumente hier bewahrt: How to maintain type parameter during TypeTag to Manifest conversion?
Hier ist der Code:
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]]
}
9
Wenn Sie naiverweise versuchen, eine Manifest
zu rufen, wenn ein TypeTag
vorhanden ist, wird der Compiler geben Ihnen einen Hinweis auf die Lösung:
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]
^
Wenn Sie also ein ClassTag
haben in Bereich, der Compiler wird in der Lage sein, die notwendigen Manifest
zu erstellen. Sie haben zwei Möglichkeiten:
einen zweiten Kontext überall gebunden hinzufügen
TypeTag
ist, wie in:def test[A : TypeTag : ClassTag] = manifest[A] // this compiles
Oder die
TypeTag
zu einemClassTag
, dann für eineManifest
fragen konvertieren: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] }
Für Vorerst ein Link, der helfen kann: http: //docs.scala-lang .org/überblicke/reflection/typetags-manifests.html – eruve