2009-11-27 10 views
9

Gibt es eine Möglichkeit, zur Laufzeit herauszufinden, welche Unterklassen von einer bestimmten Klasse existieren?Unterklassen einer gegebenen Klasse in Obj-C entdecken

Bearbeiten: Von den Antworten bisher denke ich, ich muss ein bisschen mehr klären, was ich versuche zu tun. Ich bin mir bewusst, dass dies in Cocoa keine gängige Praxis ist und dass es mit einigen Vorbehalten einhergehen kann.

Ich schreibe einen Parser mit dem dynamischen Erstellungsmuster. (Siehe das Buch Cocoa Design Patterns von Buck und Yacktman, Kapitel 5.) Grundsätzlich verarbeitet die Parser-Instanz einen Stapel und instanziiert Objekte, die wissen, wie bestimmte Berechnungen durchgeführt werden.

Wenn ich alle Unterklassen der Klasse MYCommand bekommen kann, kann ich zum Beispiel dem Benutzer eine Liste der verfügbaren Befehle zur Verfügung stellen. Im Beispiel aus Kapitel 5 verfügt der Parser über ein Substitutionswörterbuch, so dass Operatoren wie +, -, * und/verwendet werden können. (Sie sind auf MYAddCommand, etc.) zugeordnet. Für mich schien es, dass diese Information in die Unterklasse gehörte, nicht die Parser-Instanz, da sie irgendwie die Idee der dynamischen Erstellung vereitelt.

Antwort

13

Anstatt versuchen, automatisch die Unterklassen alle MYCommand zu registrieren, warum nicht das Problem in zwei Teile gespalten?

Zuerst bieten API für die Registrierung einer Klasse, etwa +[MYCommand registerClass:].

Dann erstellen Sie Code in MYCommand, das bedeutet, dass alle Unterklassen sich automatisch registrieren. Etwas wie:

@implementation MYCommand 
+ (void)load 
{ 
    [MYCommand registerClass:self]; 
} 
@end 
+0

Das sieht nach dem richtigen Weg aus. Zumal die Dokumentation erwähnt, dass die '+ load' Methode einer Klasse nach allen '+ load'-Methoden ihrer Superklassen aufgerufen wird. Vielen Dank an die anderen Leute, die auch Antworten gaben, aber ihre Antworten waren auch großartig. –

+2

Unterklassen von MyCommand werden nicht + load für ihre Oberklasse aufrufen. + load wird nur in Klassen aufgerufen, die es implementieren. –

+0

Überrascht dauerte es so lange, bis jemand mich korrigierte! Ich bin im Allgemeinen mit den Antworten hier einverstanden, dass automatische Registrierung eine schlechte Idee ist und eher ein bisschen mehr manuell gehandhabt werden sollte. –

19

Nicht direkt, nein. Sie können jedoch eine Liste aller mit der Laufzeit registrierten Klassen abrufen sowie diese Klassen für ihre direkte Superklasse abfragen. Beachten Sie, dass Sie damit nicht alle Vorfahren für die Klasse bis zum Vererbungsbaum finden können, sondern nur die unmittelbare Oberklasse.

Sie können verwenden, um die Liste der mit der Laufzeit registrierten Objekte Class abzurufen. Dann können Sie das Array durchlaufen und [NSObject superclass] auf diesen Class Objekten aufrufen, um ihre Superklasse 'Class Objekt zu erhalten. Wenn Ihre Klassen aus irgendeinem Grund NSObject nicht als ihre Stammklasse verwenden, können Sie stattdessen class_getSuperclass() verwenden.

Ich sollte auch erwähnen, dass Sie könnte denken über Ihre Anwendung Design falsch, wenn Sie das Gefühl, dass es notwendig ist, diese Art von Entdeckung zu tun ist. Höchstwahrscheinlich gibt es eine andere, konventionellere Art zu tun, was Sie zu erreichen versuchen, ohne die Objective-C-Laufzeit in Betracht zu ziehen.

+7

Ich würde es stärker sagen; Wenn Sie denken, dass Sie dies im Produktionscode tun müssen, tun Sie sehr wahrscheinlich falsch.Nach unten schauende Vererbungsintrospektion ist extrem ungewöhnlich und ist der Grund, warum die Laufzeit sie nicht direkt unterstützt. Was versuchst du zu machen? – bbum

+0

@bbum Ich habe eine Beschreibung hinzugefügt, was ich versuche zu tun. Denkst du immer noch, dass ich es sehr falsch mache? Es fällt mir schwer, über eine andere Möglichkeit nachzudenken, ohne nach Unterklassen zu suchen. –

4

Marc und Bbum schlagen es auf das Geld. Dies ist normalerweise keine gute Idee.

Allerdings haben wir Code auf unserer Wiki Cocoaheads, das dies tut: http://cocoaheads.byu.edu/wiki/getting-all-subclasses

+1

Ein weiterer Vorbehalt; Wenn Sie so etwas tun, werden Sie am Ende Klassen initialisieren, die in einer Reihenfolge initialisiert werden, in der sie möglicherweise nie zuvor initialisiert wurden. Dies sollte keine Probleme verursachen, aber manchmal aufgrund von Abhängigkeiten in den Systemklassen, die sich in Versionen ändern können. – bbum

+0

Die Beschreibung für den verknüpften Code besagt, dass dieser Ansatz nicht '+ initialize' aufruft, obwohl ich haven habe es noch nicht versucht, scheint richtig. –

0

Es gibt Code in meinem Browser Runtime Projekt here, die eine -subclassNamesForClass umfasst: Verfahren. Siehe die RuntimeReporter.[hm] Dateien.

+0

Danke, das ist ein interessantes Werkzeug, das ich meinem Gürtel hinzufügen kann. Aber ich werde mit Mikes Ansatz für diesen speziellen Fall gehen. –

+0

Ich habe festgestellt, dass der Link von @NSResponder gebrochen ist. Für diejenigen, die nach einer Möglichkeit suchen, eine Klassenhierarchie zu durchlaufen, habe ich einen [Class Hierarchy Logger] (https://github.com/sebaven/class-hierarchy-logger) geschrieben, der einen ähnlichen Ansatz verwendet. Es kann nützlich sein, wenn Sie mehr Informationen darüber benötigen, wie die Unterklassenhierarchie iteriert wird. Ich hoffe, es hilft! –

3

Ein anderer Ansatz wurde gerade von Matt Gallagher auf his blog veröffentlicht.

Verwandte Themen