Ich habe ein Protokoll und mehrere DefTypen, die es in einem Arbeitsbereich implementieren. Wie kann ich alle deftypes auflisten, die folgendes Protokoll implementieren?
Ich bin zu der Lösung gekommen, die Daten von (ns-public) filtert, aber ich mag sie nicht, weil sie etwas "Magie" benutzt, um die Arbeit zu erledigen, da ich keinen richtigen Weg gefunden habe erreiche mein Ziel mit erfüllt? und erweitert? .
Irgendwelche Ideen?
%Vor% Im Allgemeinen wird dies ein haariges Problem sein, das zu lösen ist, weil es zwei verschiedene Möglichkeiten gibt, wie ein Typ ein Protokoll erfüllen kann. Sie können jede vorhandene Java-Klasse mithilfe der Funktionen extend-type
und extend-protocol
zu einem Protokoll erweitern (dies ist eine sehr mächtige Funktion, da Sie Ihren Code so erweitern können, dass er mit integrierten Java- oder Clojure-Typen oder anderen Parteitypen, die du nicht kontrollierst). Oder Sie können eine Protokollimplementierung direkt als Teil einer Typdefinition in deftype
oder defrecord
angeben. Diese beiden Mechanismen sind unterschiedlich implementiert.
Der erste Fall (Erweiterung über extend-type
oder extend-protocol
) wird für Sie leichter zu lösen sein, da der erweiterte Typ an das Protokoll selbst angehängt wird (ein Protokoll entspricht im Wesentlichen einer generierten Java-Schnittstelle) plus eine Clojure-Map mit Metadaten zum Protokoll). Sie können die Typen finden, die das Protokoll erweitern, indem Sie den Schlüssel :impls
in der Protokollzuordnung anzeigen:
Der zweite Fall (direktes Implementieren eines Protokolls über deftype
oder defrecord
) ist schwieriger, da die für den Typ oder Datensatz generierte Java-Klasse die vom Protokoll definierte Java-Schnittstelle direkt implementiert (Sie können implementieren jede Java-Schnittstelle in deftype
oder defrecord
, nicht nur ein Protokoll). Jede Herangehensweise, um Typen zu finden, die ein Protokoll auf diese Weise erweitern, wird ein gewisses Maß an Scannen und Reflektion erfordern. Im Wesentlichen fragen Sie: "Wie kann ich alle Java-Klassen finden, die eine bestimmte Schnittstelle implementieren?"
In einer typischen Java-Anwendung könnten Sie etwas tun, um die Verzeichnisse des Klassenpfads nach .class-Dateien zu durchsuchen und nach ihnen zu schauen, aber das funktioniert in Clojure nicht, weil es sehr wohl keine .class-Dateien sind für Ihre Typen (der Bytecode wird dynamisch generiert). Wenn Sie nicht mit Ihrer eigenen Implementierung zufrieden sind, können Sie die Antwort in dieser Frage überprüfen und sehen, ob es mehr nach Ihrem Geschmack ist:
Suchen Sie nach Java-Klassen, die eine Schnittstelle implementieren