718 Stimmen

@class vs. #import

Nach meinem Verständnis sollte man eine Forward-Class-Deklaration für den Fall verwenden, dass ClassA einen ClassB-Header einschließen muss und ClassB einen ClassA-Header einschließen muss, um zirkuläre Einschlüsse zu vermeiden. Ich verstehe auch, dass eine #import ist eine einfache ifndef so dass ein Include nur einmal vorkommt.

Meine Frage lautet wie folgt: Wann verwendet man #import und wann verwendet man @class ? Manchmal, wenn ich eine @class Deklaration sehe ich eine allgemeine Compiler-Warnung wie die folgende:

warning: receiver 'FooController' is a forward class and corresponding @interface may not exist.

Ich würde das wirklich gerne verstehen, im Gegensatz zum einfachen Entfernen der @class Vorwärts-Erklärung und das Auslösen einer #import ein, um die Warnungen des Compilers zum Schweigen zu bringen.

758voto

Ben Gottlieb Punkte 84876

Wenn Sie diese Warnung sehen:

Warnung: Empfänger 'MyCoolClass' ist eine Forward-Klasse und die entsprechende @Schnittstelle darf nicht existieren

müssen Sie #import der Datei, aber Sie können dies in Ihrer Implementierungsdatei (.m) tun und die @class Deklaration in Ihrer Header-Datei.

@class beseitigt (in der Regel) nicht die Notwendigkeit, die #import Dateien, sondern verschiebt die Anforderung nur näher an den Ort, an dem die Informationen nützlich sind.

Zum Beispiel

Wenn Sie sagen @class MyCoolClass weiß der Compiler, dass er etwas wie:

MyCoolClass *myObject;

Sie muss sich um nichts anderes kümmern als um MyCoolClass eine gültige Klasse ist, und es sollte Platz für einen Zeiger auf sie reserviert werden (wirklich nur ein Zeiger). Also, in Ihrem Header, @class reicht in 90 % der Fälle aus.

Sollten Sie jedoch jemals die Notwendigkeit haben, ein myObject zu verwenden, müssen Sie dem Compiler mitteilen, um welche Methoden es sich handelt. An diesem Punkt (vermutlich in Ihrer Implementierungsdatei) müssen Sie #import "MyCoolClass.h" um dem Compiler zusätzliche Informationen mitzuteilen, die über "dies ist eine Klasse" hinausgehen.

183voto

PeyloW Punkte 36534

Drei einfache Regeln:

  • Nur #import die Superklasse und die übernommenen Protokolle in Header-Dateien ( .h Dateien).
  • #import alle Klassen und Protokolle, an die Sie in der Implementierung Nachrichten senden ( .m Dateien).
  • Forward-Deklarationen für alles andere.

Wenn Sie die Vorwärtsdeklaration in den Implementierungsdateien vornehmen, dann machen Sie wahrscheinlich etwas falsch.

110voto

Abizern Punkte 137651

Sehen Sie sich die Dokumentation zur Objective-C-Programmiersprache auf ADC

Im Abschnitt Defining a Class | Class Interface wird beschrieben, warum dies geschieht:

Die @class-Direktive minimiert die Menge an Code, die vom Compiler und Linker gesehen wird, und ist daher der einfachste Weg, um eine Forward-Deklaration eines Klassennamens zu geben. Da sie einfach ist, vermeidet sie potenzielle Probleme, die beim Import von Dateien auftreten können, die wiederum andere Dateien importieren. Wenn zum Beispiel eine Klasse eine statisch typisierte Instanzvariable einer anderen Klasse deklariert und die beiden Schnittstellendateien sich gegenseitig importieren, kann keine der beiden Klassen korrekt kompiliert werden.

Ich hoffe, das hilft.

48voto

Marc Charbonneau Punkte 40221

Verwenden Sie bei Bedarf eine Forward-Deklaration in der Header-Datei, und #import die Header-Dateien für alle Klassen, die Sie in der Implementierung verwenden. Mit anderen Worten, Sie müssen immer #import die Dateien, die Sie in Ihrer Implementierung verwenden, und wenn Sie eine Klasse in Ihrer Header-Datei referenzieren müssen, verwenden Sie ebenfalls eine Forward-Deklaration.

El Ausnahme ist, dass Sie #import eine Klasse oder ein formales Protokoll, von der bzw. dem Sie in Ihrer Header-Datei erben (in diesem Fall brauchen Sie es nicht in die Implementierung zu importieren).

24voto

vent Punkte 963

Ein weiterer Vorteil: Schnelle Zusammenstellung

Wenn Sie eine Header-Datei einbinden, führt jede Änderung darin dazu, dass die aktuelle Datei ebenfalls kompiliert wird, was jedoch nicht der Fall ist, wenn der Klassenname als @class name . Natürlich müssen Sie den Header in die Quelldatei aufnehmen

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