Warum sind alloc und init aufgerufen separat in Objective-C?
Hinweis: ich bin relativ neu in Objective-C und komme von Java und PHP.
Könnte mir jemand erklären, warum ich immer zuerst allokieren und initialisieren einer Instanz?
Konnte dies nicht getan werden in der init-Methoden wie diese:
+ (MyClass*)init {
MyClass *instance = [MyClass alloc];
[instance setFoo:@"bla"];
return instance;
}
+ (MyClass*)initWithString:(NSString*)text {
MyClass *instance = [MyClass init];
[instance setFoo:text];
return instance;
}
...
Ist das nur ein Relikt aus der alten C Tagen oder ist es etwas, das ich nicht sehe?
Ich weiß, das ist nicht ein problem, da konnte ich auch immer anrufen, alloc und init, aber da es ein wenig mühsam, ich möchte zumindest wissen, warum ich bin, es zu tun.
Ich mag die Ausdruckskraft der Sprache so weit, aber das ist etwas, dass ich möchte, um vollständig zu verstehen, um zu denken, die Objective-C Weg.
Danke!
Du musst angemeldet sein, um einen Kommentar abzugeben.
+neue landet das senden ein +alloc Nachricht an die Klasse und ein -init-Nachricht an das, was kommt zurück von +alloc.
Dem Grund, dass die Nächste ging von Stepstone-Konvention für die Verwendung der +neue Nachricht (das war ein Smalltalk-Idee) ist, dass in der Anfangszeit stießen Sie auf Situationen, in denen Sie in der Lage sein wollten initialisieren Sie das gleiche Objekt mehr als einmal.
init
Nachrichten, es sei denn, die Klasse Dokumentation, die explizit sagt, dass es sicher ist. (Definitiv nicht versuchen Sie, diese mit der Klasse Cluster.)+initialize
Nachricht, auch über threads. Und ich kann mir nicht vorstellen ein guter Grund, das zu tun[super initialize]
—Sie sind nicht so sicher, es wird nicht zurücknil
, da gibt esvoid
, und Sie garantiert, dass Ihre Oberklasse erhalteninitialize
bevor Sie das tun.+initialize
Nachricht. Wenn Sie das tun, dann haben Sie geschrieben, ein bug. Und die Dokumentation unter NSObject explizit sagt: "es ist aufgerufen, nur einmal pro Klasse". Daher, wenn Sie dabei sind zu berücksichtigen die Möglichkeit haben, sollten Sie dies tun, indem du verfolgen, wie viele Male Sie haben gerufen, und die Behauptung, dass es 1.initialize
es [sic] ist aufgerufen, nur einmal pro Klasse." Wenn alles andere ruft die gleiche Klasseinitialize
mehr als einmal, das ist ein bug, going durch alles, was die Dokumentation beide sagt und bedeutet. Wenn es kein Fehler ist, dann ist entweder die Dokumentation ist das weglassen von etwas, oder es enthält eine explizite Warnung über mehrereinitialize
Nachrichten, die ich sehen möchte.Weil eine Instanz erzeugen und initialisieren einer Instanz werden zwei separate Aufträge.
Senden Sie eine
alloc
Nachricht an die Klasse, um eine nicht initialisierte Instanz. Sie müssen dann initialisieren die Instanz, und Sie haben oft mehrere Wege, das zu tun. Zum Beispiel:Jede dieser initialisiert den string in eine völlig andere Weise. Wie initialisieren Sie die Zeichenfolge hängt davon ab, was Sie wollen, initialisieren Sie es aus.
Natürlich, niemand mag es zu schreiben
alloc
und danninit
und dannautorelease
jeder Zeit, so haben Sie in der Regel convenience-Methoden (z.B.stringWithFormat:
), dass alle drei Schritte für Sie.Edit: Für mehr auf diesem Thema, einschließlich der wesentlichen Erkenntnisse aus den Kommentatoren, siehe mein blog-Beitrag "Wiedervereinigung".
alloc
es, Sie müssenrelease
es. Diese ist nicht so intuitiv offensichtlich, wenn Sie ersetzenalloc
mitinit
in der Regel: "Wenn Sie Sie initialisieren, müssen Sierelease
es"? Warum?initWithX:
dass nicht nur initialisiert ist. Sie kann sehr gut nicht die Dokumentation gelesen (wusste nicht, dass es existiert, habe vergessen, es zu Lesen, versprochen, es zu Lesen später, habe versucht es zu Lesen aber waren undercaffeinated), aber Sie kann nicht bekommen away, ohne zu Lesen den code. Dokumentieren Methoden' zu Verhalten, ist nett, aber klare Methodennamen sind unerlässlich.[[class alloc] initWithX:]
? Wenn Sie besorgt über die Kosten einer Nachricht, anhalten; Sie sind vorzeitig optimieren. Nachrichten sind nicht so teuer mehr, und haben nicht das seit Jahren.Sehen
NSZone
.+alloc
ist eine Verknüpfung Schnitt für+allocWithZone:
, das ist ein Mechanismus, der Kakao sorgt für die Optimierung der Speicherzuweisung.So haben Sie die Möglichkeit, so etwas zu tun:
Die Idee hinter memory-Zonen ist, dass, wenn Sie eine große Anzahl ähnlicher Objekte, die Häufig zugewiesen und freigegeben werden, kann es effizienter sein, um einen separaten Speicher-zone für diese Objekte.
Um für die zonenabgrenzung, um wirksam zu sein Sie würden haben wollen
+allocWithZone:
jeder NSObject Unterklasse, daher müssen Sie separate Zuweisung und Initialisierung. Sie können erstellen und verwenden Sie alle shortcuts, die Sie wollen, wie+new
, aber unter all dem müssen Sie ein-init
Methode wird ein Objekt initialisiert, der bereits vergeben ist.", Der die Zuweisung und Initialisierung Phasen der instanzerstellung bietet viele Vorteile. Es ist möglich, jede variation des +alloc Methode der Klasse zuteilen, eine Instanz und verwenden Sie dann jedem zur Verfügung Initialisierer mit der neuen Instanz.Dies macht es möglich, erstellen Sie Ihre eigene Initialisierungs-Methoden ohne Alternative Implementierungen aller allocation-Methoden.
Neue allocation-Methoden werden selten erstellt, da die bestehenden Methoden erfüllen nahezu jeden Bedarf. Jedoch, ein oder mehrere neue Initialisierungen sind für fast jede Klasse. Durch die Trennung von Allokation und Initialisierung Phasen Initialisierung Implementierungen nur zu tun haben mit den Variablen der neuen Instanzen und können völlig ignorieren, die Fragen rund um die Zuteilung.Die Trennung vereinfacht den Prozess des Schreibens Initialisierungen. Außerdem, Kakao-standard-Initialisierungen wie -initWithCoder: arbeiten mit Instanzen unabhängig von der Art und Weise Speicher für die Instanz vergeben war.
Eine negative Folge der Trennung von Zuweisung und Initialisierung ist die Notwendigkeit bewusst zu werden, sich von Konventionen wie der designierte Initialisierer.Sie müssen wissen, mit welchen Methoden bezeichnet werden Initialisierungen und wie zu erstellen und zu dokumentieren neuen Initialisierungen in sub - Klassen. Auf lange Sicht, mit ausgewiesenen Initialisierungen vereinfacht die software-Entwicklung, aber es ist ein argument gemacht werden, dass theTwo-Phase Erstellung-Muster fügt zu Anfang der Lernkurve für Cocoa-Entwickler."
(c) Cocoa Design Patterns von Erik M. Buck, Donald A. Yacktman
Sie nicht haben, um. Sie können
[MyClass new]
. Dies ist ähnlich wie die hypothetischeinit
Methode.Grundsätzlich, Objective-C, die nicht über garbage-collection zunächst trennt, das Konzept der Speicher-Allokation und die Klasse initialisiert wird. Das ist, warum gibt es zwei unterschiedliche Methoden. Wenn Sie anrufen
alloc
Sie sind explizit zuweisen von Speicher.[[Class alloc] init]
Muster. Wie ich bereits in meiner Antwort, es als eine gute Sache, um die Speicherzuordnung explizit ein manuelles memory-management-Umgebung. Durch die Trennung das Konzept der Zuweisung von Speicher zualloc
Methode, Sie sind sich immer bewusst, dass Sie sollten ihn loslassen.Meisten Klassen haben, was Ihr bittet. Sie bekommen Antworten vor, warum dies so ist wie er ist und warum Sie nicht immer wollen die ganze Zeit, aber wenn Sie Lesen Sie die Dokumentation zu den Klassen finden Sie viele Klasse Methoden, die so agieren, und Sie werden oft verwendet.
Für NSString, die Sie haben, zum Beispiel:
Und so weiter. Und Sie würden dann verwenden Sie diese wie:
NSString *myString = [NSString stringWithFormat:@"Hello %@\n", userName];
Meisten anderen Klassen haben diese, wie NSArray:
Brauchen Sie nur die Dokumentation zu Lesen. 🙂 Und lies die anderen Antworten, warum Sie nicht wollen, zu viel.
alloc
/initWithX
- combo, dass Sie autorelease die zurückgegebenen Objekte, das ist kein unwesentlicher Unterschied.alloc : Speicher reserviert/zu den angegebenen Objekt-Referenz. Jetzt verweisen hat den Besitz der Speicher aber nicht getan hat, noch nichts. Dieser Speicher leer sein(seltensten Fällen) oder mit einigen anonymen Daten.
alloc und init : zugeordneter Arbeitsspeicher wird gereinigt/geleert. Erinnerung wird eingeleitet durch null bit.
alloc und initwithdata... : zugeordneter Arbeitsspeicher wird eingeleitet mit den gewünschten Daten berücksichtigt werden, um die Eigenschaften der Klasse.
Zum Beispiel, wenn Sie kaufen ein Grundstück bekommen Sie den Besitz. Dieses Grundstück ist gegeben, die Sie, wie es ist, ruiniert Steine oder altes Haus dabei sein dürfen. Dies ist alloc.
Wenn Sie reinigen Sie Ihre Handlung und entfernen Sie alle Schmutz und Abfall. Dies ist mit alloc init.
Wenn Sie bauen, dass in einigen wertvollen Haus wird es mehr für Sie von Bedeutung sind. Und es ist alloc initwith...