2009-06-04 4 views
13

Ich habe auf RAII und Single vs. Zweiphasen-Konstruktion/Initialisierung gelesen. Aus welchem ​​Grund auch immer, ich war bis vor kurzem in dem Zwei-Phasen-Lager, weil ich irgendwann gehört haben muss, dass es in Ihrem Konstruktor fehleranfällige Operationen sind. Ich denke jedoch, dass ich jetzt davon überzeugt bin, dass einphasig vorzuziehen ist, basierend auf Fragen, die ich zu SO und anderen Artikeln gelesen habe.Objective C Zwei-Phasen-Konstruktion von Objekten

Meine Frage ist: Warum verwendet Objective C den Zwei-Phasen-Ansatz (alloc/init) fast ausschließlich für Nicht-Convenience-Konstrukteure? Gibt es einen bestimmten Grund in der Sprache oder war es nur eine Designentscheidung der Designer?

Antwort

28

Ich habe die beneidenswerte Situation der Arbeit für den Kerl, der schrieb +alloc zurück im Jahr 1991, und ich zufällig ihm eine sehr ähnliche Frage vor ein paar Monaten zu stellen. Die Hinzufügung von +alloc war erforderlich, um +allocWithZone: bereitzustellen, das war, um Speicherpools in NeXTTSP 2.0 hinzuzufügen, wo Speicher sehr eng (4 M) war. Dadurch konnte der Aufrufer steuern, wo Objekte im Speicher zugewiesen wurden. Es war ein Ersatz für +new und seine Verwandtschaft, die (und weiterhin, obwohl niemand es verwendet) ein 1-Phasen-Konstruktor ist, basierend auf Smalltalk's new. Als Cocoa zu Apple kam, war die Verwendung von +alloc bereits fest verankert, und es gab keine Rückkehr zu +new, obwohl tatsächlich Ihre NSZone selten von signifikantem Wert ist.

So ist es nicht eine große philosophische Frage 1-phase/2-phase. In der Praxis hat Cocoa eine einphasige Konstruktion, weil Sie diese immer hintereinander in einem einzigen Aufruf ohne einen Test auf dem +alloc aufrufen (und immer sollten). Sie können es sich als eine ausgeklügelte Art der Eingabe von "neu" vorstellen.

+3

+1 Wow, ich hätte keine bessere Antwort verlangen können –

3

Meine Erfahrung ist mit C++, aber ein Nachteil von C++ 's Ein-Phasen-Initialisierung ist die Behandlung von Vererbung/virtuellen Funktionen. In C++, you can't call virtual functions during construction or destruction (naja, Sie können, es wird einfach nicht tun, was Sie erwarten). Ein zweiphasiges Init könnte das lösen (teilweise. Von dem, was ich verstehe, würde es in die richtige Klasse geroutet werden, aber das Init ist vielleicht noch nicht fertig. Du könntest immer noch damit machen) (Ich bin immer noch für die eine Phase)