webentwicklung-frage-antwort-db.com.de

Überschreiben von Methoden mithilfe von Kategorien in Objective-C

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; 
}

Funktioniert das oder ist das illegal?

86
retix

Von Apple-Dokumentation :

Obwohl Sie in der Objective-C-Sprache derzeit eine Kategorie verwenden können, um die von der Klasse übernommenen Methoden oder sogar die in der Klassenschnittstelle deklarierten Methoden zu überschreiben, wird dringend davon abgeraten . Eine Kategorie ist kein Ersatz für eine Unterklasse. Die Verwendung einer Kategorie zum Überschreiben von Methoden weist mehrere erhebliche 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 super aufrufen. Wenn jedoch eine Kategorie eine in der Klasse der Kategorie vorhandene Methode überschreibt, besteht keine Möglichkeit, die ursprüngliche Implementierung aufzurufen.

  • Eine Kategorie kann Methoden, die in einer anderen Kategorie derselben Klasse deklariert wurden, 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 zu überschreiben versuchen, wurde möglicherweise selbst in einer Kategorie implementiert, und 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 Delegatmethode windowWillClose: 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.

142
Benoît

Sie können dies tun, indem Sie den Ansatz Klassencluster anpassen oder Methoden-Swizzling verwenden.

Andernfalls ist das Verhalten von zwei oder mehr kategorisierten Methoden ndefiniert

18
Martin Babacaev

Alter 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 zu 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 Superklasse) identisch ist, ist das Verhalten nicht definiert, bei welcher Methodenimplementierung verwendet wird Laufzeit. Dies ist weniger wahrscheinlich, wenn Sie Kategorien mit eigenen Klassen verwenden, kann jedoch Probleme verursachen, wenn Sie Kategorien verwenden, um Methoden zu Standard-Cocoa- oder Cocoa Touch-Klassen hinzuzufügen.

Es ist Apple mit einer leichteren Berührung, aber der Hauptpunkt ist der gleiche: Sie laden eine Katastrophe ein, weil das unvorhersehbare Verhalten still ist.

8
AmitaiB

Es ist wichtig zu beachten, dass eine Kategorie auch verwendet werden kann, um vorhandene Methoden in der Basisklasse (z. B. die Laufwerksmethode 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 das Verhalten für eine andere Kategorie erneut ändern möchten, kann Objective-C nicht wissen, welche Implementierung verwendet werden soll. Unterklassen ist in einer solchen Situation fast immer eine bessere Option.

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

2
Vinuta