Überschreiben von Methoden mithilfe von Kategorien in Objective-C

87

Kann ich eine Klassenkategorie verwenden, um eine Methode zu überschreiben, die bereits mithilfe einer Kategorie implementiert wurde? So was:

1) Ursprüngliche Methode

-(BOOL) method {
  return true;
}

2) Überschriebene Methode

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Wird das funktionieren oder ist das illegal?

retix
quelle

Antworten:

145

Aus der Apple-Dokumentation :

Obwohl Sie in der Objective-C-Sprache derzeit eine Kategorie verwenden können, um Methoden zu überschreiben, die die Klasse erbt, oder sogar Methoden, die in der Klassenschnittstelle deklariert sind, wird davon dringend abgeraten . Eine Kategorie ist kein Ersatz für eine Unterklasse. Die Verwendung einer Kategorie zum Überschreiben von Methoden weist mehrere wesentliche Mängel auf:

  • Wenn eine Kategorie eine geerbte Methode überschreibt, kann die Methode in der Kategorie wie üblich die geerbte Implementierung über eine Nachricht an aufrufen super. Allerdings , wenn eine Kategorie eine Methode überschreibt , die in der Kategorie der Klasse vorhanden ist , gibt es keine Möglichkeit , die ursprüngliche Implementierung aufzurufen .

  • Eine Kategorie kann Methoden, die in einer anderen Kategorie derselben Klasse deklariert sind, nicht zuverlässig überschreiben.

    Dieses Problem ist von besonderer Bedeutung, da viele der Cocoa-Klassen mithilfe von Kategorien implementiert werden. Eine vom Framework definierte Methode, die Sie überschreiben möchten, wurde möglicherweise selbst in einer Kategorie implementiert. Daher ist nicht definiert, welche Implementierung Vorrang hat.

  • Das Vorhandensein einiger Kategoriemethoden kann zu Verhaltensänderungen in allen Frameworks führen. Wenn Sie beispielsweise die windowWillClose:Delegatmethode in einer Kategorie in NSObject überschreiben, antworten alle Fensterdelegierten in Ihrem Programm mit der Kategoriemethode. Das Verhalten aller Ihrer Instanzen von NSWindow kann sich ändern. Kategorien, die Sie einer Framework-Klasse hinzufügen, können mysteriöse Verhaltensänderungen verursachen und zu Abstürzen führen.

Benoît
quelle
Danke, aber das weiß ich schon. Ich frage mich nur, ob mein Fall legal ist oder nicht. Mein Fall unterscheidet sich ein wenig von Dokumenten. :)
Retix
Warum ist es anders? Der Arzt sagt, dass es legal ist, wenn die ursprüngliche Methode nicht zu einer Kategorie gehört, aber dringend davon abgeraten wird. Dann können Sie es tun ...
Benoît
1
Danke für Deinen Ratschlag. Ich bin arm in dieser Sprache. Ich habe neue Informationen von Ihnen erhalten.
Retix
1
Ist es richtig, die in der Kategorie der Superklasse deklarierte und implementierte Category-Methode zu überschreiben?
BergP
2
Der Link ist defekt, ist das die neue Version? developer.apple.com/library/ios/documentation/Cocoa/Conceptual/…
RndmTsk
18

Sie können dies durch eine Anpassung der Klasse Cluster - Ansatz oder unter Verwendung von Methoden Swizzling Technik.

Andernfalls ist das Verhalten von zwei oder mehr kategorisierten Methoden undefiniert

Martin Babacaev
quelle
9

Der alte Dokumentationslink ist tot. Der beste Ersatz, den ich finden konnte, war hier: Apple Docs :

Vermeiden Sie Konflikte mit Kategorienamen

Da die in einer Kategorie deklarierten Methoden einer vorhandenen Klasse hinzugefügt werden, müssen Sie bei Methodennamen sehr vorsichtig sein.

Wenn der Name einer in einer Kategorie deklarierten Methode mit einer Methode in der ursprünglichen Klasse oder einer Methode in einer anderen Kategorie in derselben Klasse (oder sogar einer Oberklasse) identisch ist, ist das Verhalten undefiniert, bei welcher Methodenimplementierung verwendet wird Laufzeit. Dies ist weniger wahrscheinlich, wenn Sie Kategorien mit Ihren eigenen Klassen verwenden, kann jedoch Probleme verursachen, wenn Sie Kategorien verwenden, um Methoden zu Standardklassen von Cocoa oder Cocoa Touch hinzuzufügen.

Es ist Apple, der eine leichtere Note verwendet, aber der Hauptpunkt ist der gleiche: Sie laden eine Katastrophe ein, weil das unvorhersehbare Verhalten still ist.

AmitaiB
quelle
2

Es ist wichtig zu beachten, dass eine Kategorie auch verwendet werden kann, um vorhandene Methoden in der Basisklasse (z. B. die Antriebsmethode der Car-Klasse) zu überschreiben. Sie sollten dies jedoch niemals tun. Das Problem ist, dass Kategorien eine flache Organisationsstruktur haben. Wenn Sie eine vorhandene Methode in Car + Maintenance.m überschreiben und dann entscheiden, dass Sie ihr Verhalten erneut mit einer anderen Kategorie ändern möchten, kann Objective-C nicht wissen, welche Implementierung verwendet werden soll. Unterklassen sind in einer solchen Situation fast immer eine bessere Option.

In diesem Tutorial finden Sie http://rypress.com/tutorials/objective-c/categories

Vinuta
quelle