Veränderlichkeitsmuster in Objective C und C ++

8

Nachdem ich kürzlich eine Entwicklung für das iPhone gemacht habe, bin ich auf ein interessantes Designmuster gestoßen, das im iPhone SDK sehr häufig verwendet wird, was die Veränderlichkeit von Objekten betrifft.

Es scheint der typische Ansatz zu sein, eine unveränderliche Klasse NSFoo zu definieren und daraus einen veränderlichen Nachkommen NSMutableFoo abzuleiten. Im Allgemeinen definiert die NSFoo -Klasse Datenelemente, Getter und schreibgeschützte Operationen und die abgeleitete NSMutableFoo fügt sie zu Setter- und Mutationsoperationen hinzu.

Da ich mit C ++ besser vertraut bin, konnte ich nicht anders als zu bemerken, dass dies ein völliges Gegenteil zu dem zu sein scheint, was ich tun würde, wenn ich denselben Code in C ++ schreiben würde. Während Sie sicherlich diesen Ansatz verwenden könnten, scheint mir ein prägnanterer Ansatz darin zu bestehen, eine einzige Klasse Foo zu erstellen, Getter und schreibgeschützte Operationen als const functions zu markieren und auch zu implementieren die veränderbaren Operationen und Setter in derselben Klasse. Sie würden dann mit einer veränderbaren Klasse enden, aber die Typen Foo const* , Foo const& usw. sind alle das unveränderliche Äquivalent.

Ich denke, meine Frage ist, macht meine Einschätzung der Situation Sinn? Ich verstehe, warum Objective-C die Dinge anders macht, aber gibt es irgendwelche Vorteile für den Zwei-Klassen-Ansatz in C ++, den ich verpasst habe? Oder verpasse ich den Punkt gänzlich?

Keine allzu ernste Frage - mehr für meine eigene Neugier als alles andere.

    
Mac 09.06.2010, 23:51
quelle

2 Antworten

4

Objective-C ist zu dynamisch. In C ++ wird const-qualification zur Kompilierzeit erzwungen, und alle Verletzungen der const-Qualifizierung zur Laufzeit (z. B. das Ändern eines const-qualifizierten Objekts durch einen nicht-const-qualifizierten Zeiger) ist ein nicht definiertes Verhalten.

Es ist teilweise dasselbe wie der Grund, warum es in Objective-C keine privaten Methoden gibt. Es steht Ihnen frei, die gewünschte Nachricht an ein beliebiges Objekt zu senden. Die Laufzeitverteilung nimmt ein Objekt und eine Nachricht und löst eine Methodenimplementierung auf, die aufgerufen werden soll.

Wenn const qualifizierte Objekte nur const qualifizierte Methoden aufrufen könnten, würde dies die dynamische Natur von Objective-C und Foundation komplett ruinieren, da eine solche Überprüfung zur Laufzeit durchgeführt werden müsste (erste Prüfung würde bestimmen, ob die Nachricht sended wird in eine Const-qualifizierte Implementierung für diese spezifische Instanz aufgelöst und eine weitere Prüfung, um festzustellen, ob die Instanz selbst const-qualifiziert ist. Betrachten Sie dieses theoretische Beispiel:

%Vor%

Plötzlich verliert man an Dynamik. So wie es jetzt ist, können veränderbare und unveränderliche Objekte in einer unveränderlichen oder veränderlichen Sammlung zusammensitzen.

Eine änderbare Unterklasse behält die dynamische Natur von Objective-C und hält die Laufzeit einfach. Vor einiger Zeit gab es ein ähnliches Thema über private Methoden.

    
dreamlax 10.06.2010, 00:53
quelle
0

Gedanken ...

Mac, wie Sie wissen, in C ++, können Sie sich "A" und "const A" als zwei verschiedene Typen vorstellen, deren einzige Beziehungen

sind
  1. "A" und "A & amp;" kann implizit in "const A" und "const A & amp;", etc ...
  2. umgewandelt werden
  3. "const A & amp;" kann const_cast zu "A & amp;", etc ...
  4. sein

Der Compiler übernimmt die Vererbung und Propagierung des type-modifiers durch Ausdrücke usw.

Ich würde vermuten, dass die NS-Leute die ..Mutable .. Konvention aus verschiedenen Gründen gewählt haben. Meine erste Vermutung ist, dass ich glaube, dass, als NextStep ursprünglich entwickelt wurde, C keine Unterstützung für "const" hatte und es immer noch keine Objektorientierung hat. Und noch wichtiger: Sie wollten bestimmte Optimierungen in ihren veränderbaren gegen unveränderlichen Objektimplementierungen. Zum Beispiel kann es in einer unveränderlichen String-Klasse wie NSString nützlich sein, Strings zu "poolen". Dadurch können doppelte Zeichenfolgen atomisiert werden und der Prozess benötigt möglicherweise weniger Speicher. (Es hat gewisse Nachteile, aber es gibt immer Kompromisse.)

In C ++ könnten Sie in die gleiche Richtung gehen, indem Sie Copy-on-Write verstehen. std :: string soll dies tun.

Interessantes Thema,
Will Bradley

    
Will Bradley 10.06.2010 00:35
quelle