Klassenerweiterung gegen Klassenkategorie

81

Klassenerweiterungen @interface Class () sind viel leistungsfähiger und können Variablen in die Klasse einfügen. Kategorien @interface Class (Category)können nicht.

Welche anderen Unterschiede gibt es und wann sollte man eine Kategorie über eine Klassenerweiterung verwenden?

David
quelle
Kategorien sind tatsächlicher Code. Auf diese Weise fügen Sie einer Klasse Funktionen hinzu. Erweiterungen sind (ganz allgemein) eher syntaktischer Zucker, um anderen Programmierern bestimmte Vorstellungen über Datenschutz usw. zu signalisieren. Erweiterungen enthalten keinen Code und sind kein Code.
Fattie

Antworten:

90

Der Hauptunterschied besteht darin, dass der Compiler bei einer Erweiterung erwartet, dass Sie die Methoden in Ihrem main implementieren @implementation, während Sie bei einer Kategorie einen separaten @implementationBlock haben. Sie sollten also so ziemlich nur eine Erweiterung oben in Ihrer Hauptdatei .mverwenden (der einzige Ort, an dem Sie sich übrigens für Ivars interessieren sollten) - es soll genau das sein, eine Erweiterung .

jtbandes
quelle
40
Eine Erweiterung eignet sich am besten für private Methoden, die Sie in Ihrer .mDatei deklarieren möchten . Ich benutze es die ganze Zeit dafür. Kategorien sind nützlicher, wenn Sie Ihre Methoden in verschiedene Abschnitte gruppieren möchten - Kategorien :) - oder wenn Sie vorhandenen Klassen, die Sie nicht erstellt haben, Code hinzufügen möchten.
Jtbandes
1
Sie können auch zusätzlichen Speicher für Klassenerweiterungen mithilfe von Eigenschaften hinzufügen.
Pauls
22
Klassenerweiterungen wurden auch speziell entwickelt, um die öffentliche readonlyund private Nutzung einer Immobilie zu ermöglichen readwrite. Mit Kategorien geht das nicht (eine bewusste Designwahl).
bbum
Warum verwendet Google Kategorie, um private Methoden anstelle von Erweiterungen zu implementieren? zB code.google.com/p/gdata-objectivec-client/source/browse/trunk/…
Ryan
Für Erweiterungen müssen alle Methoden im @ implementierungsblock implementiert sein. Außerdem werden Variablen erweitert. Aber wir versuchen im Grunde, einige der privaten Methoden zu verwenden, anstatt private Variablen zu verwenden. In diesem Fall bevorzugen wir die Kategorie anstelle der Erweiterung
Ankit Thakur,
27

Eine Klassenerweiterung weist eine gewisse Ähnlichkeit mit einer Kategorie auf, kann jedoch nur einer Klasse hinzugefügt werden, für die Sie zur Kompilierungszeit über den Quellcode verfügen (die Klasse wird gleichzeitig mit der Klassenerweiterung kompiliert). Die von einer Klassenerweiterung deklarierten Methoden werden im @ implementierungsblock für die ursprüngliche Klasse implementiert, sodass Sie beispielsweise keine Klassenerweiterung für eine Framework-Klasse wie eine Cocoa- oder Cocoa Touch-Klasse wie NSString deklarieren können.

Die Syntax zum Deklarieren einer Klassenerweiterung ähnelt der Syntax für eine Kategorie und sieht folgendermaßen aus:

@interface ClassName ()
@end

Da in den Klammern kein Name angegeben ist, werden Klassenerweiterungen häufig als anonyme Kategorien bezeichnet.

Im Gegensatz zu regulären Kategorien kann eine Klassenerweiterung einer Klasse eigene Eigenschaften und Instanzvariablen hinzufügen. Wenn Sie eine Eigenschaft in einer Klassenerweiterung wie folgt deklarieren:

@interface XYZAnimal () {
    id _someCustomInstanceVariable;
}
...
@end

IMHO ist es am besten, sich Klassenerweiterungen als private Schnittstelle zu einer Klasse vorzustellen. Die primäre Schnittstelle (in Ihrer .h-Datei) fungiert als öffentliche Schnittstelle, die den Verhaltensvertrag der Klasse mit anderen Klassen definiert.

Verwenden Sie Klassenerweiterungen, um private Informationen auszublenden

Klassenerweiterungen werden häufig verwendet, um die öffentliche Schnittstelle um zusätzliche private Methoden oder Eigenschaften zu erweitern, die in der Implementierung der Klasse selbst verwendet werden können. Es ist beispielsweise üblich, eine Eigenschaft als schreibgeschützt in der Schnittstelle, aber als schreibgeschützt in einer über der Implementierung deklarierten Klassenerweiterung zu definieren, damit die internen Methoden der Klasse den Eigenschaftswert direkt ändern können.

Beispielsweise könnte die XYZPerson-Klasse eine Eigenschaft namens uniqueIdentifier hinzufügen, mit der Informationen wie eine Sozialversicherungsnummer in den USA erfasst werden sollen.

Normalerweise ist ein großer Papierkram erforderlich, um einer Person in der realen Welt einen eindeutigen Bezeichner zuzuweisen. Daher kann die XYZPerson-Klassenschnittstelle diese Eigenschaft als schreibgeschützt deklarieren und eine Methode bereitstellen, mit der ein Bezeichner wie folgt zugewiesen werden muss:

@interface XYZPerson : NSObject
    ...
    @property (readonly) NSString *uniqueIdentifier;
    - (void)assignUniqueIdentifier;
@end

Damit die XYZPerson-Klasse die Eigenschaft intern ändern kann, ist es sinnvoll, die Eigenschaft in einer Klassenerweiterung neu zu deklarieren, die oben in der Implementierungsdatei für die Klasse definiert ist:

@property (readwrite) NSString *uniqueIdentifier;

Hinweis: Das Attribut readwrite ist optional, da es die Standardeinstellung ist. Sie können es aus Gründen der Übersichtlichkeit beim erneuten Deklarieren einer Eigenschaft verwenden.

John Doe
quelle
6

Kategorien sind eine Objective-C-Sprachfunktion, mit der Sie einer vorhandenen Klasse neue Methoden hinzufügen können. Erweiterungen sind ein Sonderfall von Kategorien, mit denen Sie Methoden definieren können, die im Hauptimplementierungsblock implementiert werden müssen.

Private Deklarationen können sich in Klassenerweiterungen befinden, bei denen es sich hauptsächlich um einige Eigenschaften handelt, da wir keine Methode deklarieren müssen, bevor wir sie aufrufen.

Julie Yu
quelle
"Das muss im Hauptimplementierungsblock deklariert werden." -> das muss im Hauptimplementierungsblock "implementiert" werden
Fawkes
Danke, ich habe es geändert.
Julie Yu
0

ios-Erweiterung ähnlich wie c #, Java-abstrakte Klasse oder Schnittstelle
ios-Kategorie ähnlich wie c # -Klassenerweiterung

Add080bbA
quelle
Java unterstützt keine Erweiterungsmethoden
someUser
Es tut uns leid ! Tippfehler kopieren und einfügen. ios-Kategorie ähnlich der c # -Klassenerweiterung.
Add080bbA
Können Sie ein Beispiel hinzufügen?
Pedro Trujillo