2 Stimmen

Wie erstelle ich eine file-scope-Klasse in Objective-C?

Ich habe das Original belassen, damit die Leute den Kontext der Kommentare verstehen können. Ich hoffe, dass dieses Beispiel besser erklärt, worum es mir geht.

Kann ich in Obj-C eine Klasse mit Dateisichtbarkeit erstellen?

Zum Beispiel habe ich eine Methode-sqizzling Kategorie auf NSNotificationCenter geschrieben, die automatisch jeden Beobachter entfernen wird, wenn es deallocs.

Ich verwende eine Hilfsklasse in der Implementierung, und um Namenskollisionen zu vermeiden, habe ich ein Namensschema entwickelt. Die Kategorie ist NSNotificationCenter (WJHAutoRemoval), also heißt die private Hilfsklasse, die in diesem Code verwendet wird,...

WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver

Das ist ein ganz schöner Brocken, und im Moment mache ich nur das hier...

#define BlockObserver WJH_NSNotification_WJHAutoRemoval__Private__BlockObserver

und verwenden Sie einfach BlockObserver im Code.

Diese Lösung gefällt mir jedoch nicht.

Ich möchte dem Compiler mitteilen: "Hey, diese Klasse heißt Bar. Mein Code wird auf sie als Bar zugreifen, aber ich bin wirklich der Einzige, der das wissen muss. Erfinde selbst einen ausgefallenen Namen, oder noch besser, exportiere das Symbol gar nicht erst, denn ich bin der Einzige, den das interessieren sollte."

Für einfaches C würde ich "static" und für C++ "namespace { }" verwenden.

Was ist die bevorzugte/beste/einzige Methode, dies in Obj-C zu tun?

Ursprüngliche Frage

Ich möchte eine Hilfsklasse innerhalb der Implementierung einer anderen Klasse verwenden. Ich möchte jedoch keine externe Verknüpfung. Im Moment bin ich nur machen die Helfer-Klasse Name schmerzlich eindeutig, so dass ich nicht doppelte Linker Symbole erhalten.

Ich kann statische C-Funktionen verwenden, aber ich möchte eine Hilfsklasse schreiben, mit Linker Sichtbarkeit nur innerhalb der Kompilierungseinheit.

Ich möchte zum Beispiel etwas wie das Folgende in mehreren .m-Dateien haben, wobei jeder "Helper" nur in dieser Datei vorkommt und keine andere Kompiliereinheit Zugriff auf den Linker hat. Wenn ich dies in 10 verschiedenen Dateien hätte, würde ich 10 separate Klassen haben.

@interface Helper : NSObject
...
@end

@implementation Helper : NSObject
...
@end

Ich habe nirgendwo auch nur einen Hinweis darauf finden können, und meine schwachen Versuche, der Schnittstelle/Implementierung "static" voranzustellen, waren fehlerhaft.

Danke!

3voto

mttrb Punkte 8266

Ich glaube nicht, dass Sie in der Lage sein werden, zu tun, was Sie wegen der Objective-C Runtime wollen. Alle Ihre Klassen werden in die Runtime geladen und mehrere Klassen mit demselben Namen werden miteinander in Konflikt geraten.

Objective-C ist eine dynamische Sprache. Im Gegensatz zu anderen Sprachen, die Methodenaufrufe zur Kompilierzeit binden, führt Objective-C die Methodenauflösung beim Aufruf (bei jedem Aufruf) durch. Die Laufzeit findet die Klasse in der Laufzeit und findet dann die Methode in der Klasse. Die Laufzeitumgebung kann keine unterschiedlichen Klassen mit demselben Namen unterstützen, und Objective-C unterstützt keine Namespaces, um Ihre Klassen voneinander zu trennen.

Wenn Ihr Helper Klassen in jedem Fall unterschiedlich sind, benötigen sie unterschiedliche Klassennamen (mehrere Klassen mit demselben Namen halte ich in jeder Sprache für eine schlechte Idee). Wenn sie gleich sind, warum wollen Sie sie dann getrennt deklarieren.

Ich denke, Sie müssen Ihre Strategie überdenken, da das, was Sie zu tun versuchen, nicht sehr nach Objective-C oder Cocoa klingt.

0voto

Rob Napier Punkte 265102

Es gibt keine Möglichkeit, eine Klasse "versteckt" zu machen. Wie mttrb anmerkt, sind Klassen über die Laufzeit namentlich zugänglich. Das ist nicht wie bei C und C++, wo Klassen nur Symbole sind, die vom Linker in Adressen aufgelöst werden. Jede Klasse wird in die Klassenhierarchie eingefügt.

Aber mir ist nicht klar, warum Sie das überhaupt brauchen. Wenn Sie eine private Klasse haben WJHAutoRemovalHelper oder was auch immer, es ist sehr unwahrscheinlich, dass sie mit jemand anderem kollidiert, genauso wenig wie private Apple-Klassen oder private Framework-Klassen von Drittanbietern kollidieren. Es gibt keinen Grund, heroische Anstrengungen zu unternehmen, um sie unkenntlich zu machen; das Präfix WJHAutoRemoval sollte ausreichen, um sie einzigartig zu machen. Gibt es ein tieferes Problem, das Sie zu lösen versuchen?

BTW als eine Nebenbemerkung: Wie implementieren Sie den Rest von diesem? Sind Sie ISA-swizzling den Beobachter zu überschreiben seine dealloc? Das scheint eine Menge komplizierter Code zu sein, um eine sehr kleine Sache etwas bequemer zu machen.


Was die Frage der "privaten" Klassen betrifft, so ist das, was Sie vorschlagen, möglich, wenn Sie es von Hand machen, aber es gibt keinen Grund dafür. Sie können einen zufälligen, eindeutigen Klassennamen generieren, rufen objc_allocateClassPair() y objc_registerClassPair zu, und weisen Sie diese dann einem Class Variable zur Laufzeit. (Und rufen Sie dann class_addMethod y class_addIvar um sie aufzubauen. Sie können dann immer auf diese Variable zurückgreifen, wenn Sie sie brauchen. Sie ist natürlich auch zur Laufzeit zugänglich, indem man objc_getClassList , aber es wird kein Symbol für den Klassennamen im System vorhanden sein.

Aber das ist eine Menge Arbeit und Komplexität für keinen Nutzen. In ObjC wird nicht viel Zeit darauf verwendet, das Programm vor sich selbst zu schützen, wie es in C++ der Fall ist. Es verwendet Namenskonventionen und Compiler-Warnungen, um Ihnen mitzuteilen, wenn Sie etwas falsch machen, und erwartet, dass Sie als guter Programmierer es vermeiden werden, etwas falsch zu machen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X