Die Antwort ist ... na ja ... einfach. Einfachheit und Konsistenz in der Tat.
Objective-C ist zum Zeitpunkt des Versands der Methode rein dynamisch. Insbesondere durchläuft jeder Methodenversand genau den gleichen dynamischen Methodenauflösungspunkt wie jeder andere Methodenversand. Zur Laufzeit hat jede Methodenimplementierung genau die gleiche Exposition und alle von der Objective-C-Laufzeit bereitgestellten APIs, die mit Methoden und Selektoren arbeiten, funktionieren für alle Methoden gleich.
Wie viele (sowohl hier als auch in anderen Fragen) geantwortet haben, werden private Methoden zur Kompilierungszeit unterstützt. Wenn eine Klasse keine Methode in ihrer öffentlich verfügbaren Schnittstelle deklariert, ist diese Methode für Ihren Code möglicherweise nicht vorhanden. Mit anderen Worten, Sie können alle verschiedenen Kombinationen der Sichtbarkeit erzielen, die zur Kompilierungszeit gewünscht werden, indem Sie Ihr Projekt entsprechend organisieren.
Das Duplizieren derselben Funktionalität in die Laufzeit hat wenig Vorteile. Es würde eine enorme Menge an Komplexität und Overhead hinzufügen. Und selbst bei all dieser Komplexität würde es nicht alle außer den gelegentlichsten Entwicklern daran hindern, Ihre angeblich "privaten" Methoden auszuführen.
BEARBEITEN: Eine der Annahmen, die mir aufgefallen sind, ist, dass private Nachrichten die Laufzeit durchlaufen müssen, was zu einem potenziell hohen Overhead führen kann. Ist das absolut wahr?
Ja, so ist es. Es gibt keinen Grund anzunehmen, dass der Implementierer einer Klasse nicht alle in der Implementierung enthaltenen Objective-C-Funktionen verwenden möchte, und dies bedeutet, dass ein dynamischer Versand erfolgen muss. Es gibt jedoch keinen besonderen Grund, warum private Methoden nicht mit einer speziellen Variante von ausgeliefert werden könnten objc_msgSend()
, da der Compiler wissen würde, dass sie privat sind. Dies könnte erreicht werden, indem der Class
Struktur eine Nur-Privat-Methodentabelle hinzugefügt wird .
Es gäbe keine Möglichkeit für eine private Methode, diese Prüfung kurzzuschließen oder die Laufzeit zu überspringen.
Die Laufzeit konnte nicht übersprungen werden, aber die Laufzeit musste nicht unbedingt nach privaten Methoden suchen.
Es gibt jedoch keinen Grund, warum ein Dritter objc_msgSendPrivate()
ein Objekt außerhalb der Implementierung dieses Objekts nicht absichtlich aufrufen könnte , und einige Dinge (z. B. KVO) müssten dies tun. Tatsächlich wäre dies nur eine Konvention und in der Praxis kaum besser, als den Selektoren privater Methoden ein Präfix voranzustellen oder sie im Schnittstellenheader nicht zu erwähnen.
Dies würde jedoch die reine Dynamik der Sprache untergraben. Nicht mehr würde jeder Methodenversand einen identischen Versandmechanismus durchlaufen. Stattdessen würden Sie in einer Situation zurückbleiben, in der sich die meisten Methoden in eine Richtung verhalten und eine kleine Handvoll nur anders sind.
Dies geht über die Laufzeit hinaus, da es in Cocoa viele Mechanismen gibt, die auf der konsistenten Dynamik von Objective-C aufbauen. Beispielsweise müssten sowohl die Schlüsselwertcodierung als auch die Schlüsselwertbeobachtung entweder stark modifiziert werden, um private Methoden zu unterstützen - höchstwahrscheinlich durch Schaffung einer ausnutzbaren Lücke - oder private Methoden wären nicht kompatibel.