In Scala nehme ich an, dass ich eine Fall-Klasse wie folgt habe:
%Vor% Gibt es eine Möglichkeit für mich, eine Seq[(String, Class[_])]
oder besser noch Seq[(String, Manifest)]
zu erhalten, die die Parameter der Fallklasse beschreibt?
Ich bin es wieder (zwei Jahre später). Hier ist eine andere, andere Lösung mit Scala Reflexion. Es ist inspiriert von einem Blogpost , die selbst von einem Stack Overflow Austausch inspiriert wurde. Die folgende Lösung ist auf die obige Frage des ursprünglichen Posters spezialisiert.
Fügen Sie in einer Kompilierungseinheit (eine REPL :paste
oder eine kompilierte JAR) scala-reflect
als Abhängigkeit ein und kompilieren Sie Folgendes (getestet in Scala 2.11, könnte in Scala 2.10 funktionieren):
Und in einer anderen Kompilierungseinheit (die nächste Zeile in der REPL oder Code mit dem vorherigen als eine Abhängigkeit kompiliert), verwenden Sie es wie folgt:
%Vor%Es scheint übertrieben zu sein, aber ich konnte es nicht kürzer kriegen. Hier ist was es tut:
caseClassFields
erstellt ein intermediate CaseClassFieldsExtractor
, das implizit entsteht, seine Ergebnisse meldet und verschwindet. CaseClassFieldsExtractor
ist ein Merkmal mit einem Begleitobjekt, das eine anonyme konkrete Unterklasse dieses Merkmals mithilfe eines Makros definiert. Es ist das Makro, das die Felder Ihrer Fallklasse überprüfen kann, da es umfangreiche Informationen auf Compiler-Ebene über die Fallklasse enthält. CaseClassFieldsExtractor
und sein Companion-Objekt müssen in einer vorherigen Kompilierungseinheit deklariert sein, die die Fallklasse überprüft, damit das Makro zu dem Zeitpunkt existiert, an dem Sie es verwenden möchten. WeakTypeTag
übergeben. Dies ergibt eine Scala-Struktur mit vielen Musterabgleich und keine Dokumentation, die ich finden konnte. CaseClassFieldsExtractor
. caseClassFields
) definiert und eingegrenzt werden, ohne dass es zu früh aufgerufen wird, wenn es noch nicht definiert ist. Alle Kommentare, die diese Lösung verbessern oder erklären könnten, wie genau die "implicits" tun, was sie tun (oder ob sie entfernt werden können), sind willkommen.
Ich beantworte meine eigene Frage, um eine Basislösung bereitzustellen, aber ich suche auch nach Alternativen und Verbesserungen.
Eine Option, die auch mit Java kompatibel und nicht auf Fallklassen beschränkt ist, ist ParaNamer . In Scala besteht eine weitere Möglichkeit darin, die ScalaSig
Bytes, die an generierte Klassendateien angehängt sind, zu analysieren. Beide Lösungen funktionieren nicht in der REPL.
Hier ist mein Versuch, die Namen der Felder aus ScalaSig
(die Scalap und Scala 2.8.1 verwendet) zu extrahieren:
Haftungsausschluss: Ich verstehe die Struktur von ScalaSig nicht wirklich und dies sollte als Heuristik betrachtet werden. Dieser Code trifft insbesondere die folgenden Annahmen:
ClassSymbol
. MethodEntry
mit dem Namen <init>
, dessen Besitzer die ID 0 hat. Es wird fehlschlagen (wegen ScalaSig
) bei verschachtelten Fallklassen.
Diese Methode gibt auch nur Class
Instanzen und nicht Manifest
s zurück.
Bitte zögern Sie nicht, Verbesserungen vorzuschlagen!
Hier ist eine andere Lösung, die Plain-Java-Reflektion verwendet.
%Vor% Um eine Seq[(String, Class[_])]
zu erhalten, können Sie dies tun:
Ich bin mir nicht sicher, wie ich Manifests
bekommen kann.
Tags und Links scala reflection case-class