Wenn ich Objective-C lerne und Beispielcode lese, stelle ich fest, dass Objekte normalerweise mit dieser Methode erstellt werden:
SomeObject *myObject = [[SomeObject alloc] init];
anstatt:
SomeObject *myObject = [SomeObject new];
Gibt es einen Grund dafür, da ich gelesen habe, dass sie gleichwertig sind?
objective-c
oop
willc2
quelle
quelle
Antworten:
Hier gibt es eine Reihe von Gründen: http://macresearch.org/difference-between-alloc-init-and-new
Einige ausgewählte sind:
new
unterstützt keine benutzerdefinierten Initialisierer (wieinitWithString
)alloc-init
ist expliziter alsnew
Die allgemeine Meinung scheint zu sein, dass Sie alles verwenden sollten, was Sie möchten.
quelle
+newWithString:
, wenn Sie bereits implementiert haben-initWithString
. Nicht so häufig. Persönlich benutze ich immer,new
wenn der vorgesehene Initialisiererinit
so kurz und bündig ist.+newWithString:
. Das bricht die Trennung von Bedenken. Wenn Sie es-init
trotzdem nur verwenden möchten , gibt es keinen Grund, es nicht nur zu verwenden+new
.[[NSString alloc] initWithFormat:...]
und[NSString stringWithFormat:...]
sind beide gleichwertig. Wollen Sie damit sagen, dass Apple gegen die Trennung von Bedenken verstoßen hat und dies nicht auf diese Weise hätte implementieren sollen? (Hinweis: Ich versuche nicht herablassend zu sein; ich möchte nur mehr Informationen erhalten und wissen, ob es manchmal eine schlechte Idee ist, Apples Führung zuSehr alte Frage, aber ich habe ein Beispiel nur zum Spaß geschrieben - vielleicht findest du es nützlich;)
In der Hauptfunktion beide Aussagen:
und
Ergebnis in der gleichen Ausgabe:
quelle
[[InitAllocNewTest alloc] init]
wird nicht kompiliert, solange es nicht[InitAllocNewTest new]
betroffen ist. (Entschuldigung für fehlende Zeilenumbrüche usw.)+new
entspricht+alloc/-init
derNSObject
Implementierung von Apple . Es ist höchst unwahrscheinlich, dass sich dies jemals ändern wird. Abhängig von Ihrem Paranoia-Level+new
scheint die Dokumentation von Apple für eine Änderung der Implementierung (und einen Verstoß gegen die Äquivalenz) in der Zukunft zu ermöglichen. Aus diesem Grund vermeidet die Objective-C-Community im Allgemeinen, weil "explizit ist besser als implizit" und aus Gründen der historischen Kontinuität+new
. In der Regel können Sie jedoch die jüngsten Java-Benutzer von Objective-C anhand ihrer hartnäckigen Verwendung von erkennen+new
.quelle
+new
es das seit den nächsten Tagen gibt. Wenn irgendetwas+new
ein Zeichen für jemanden ist, der vor langer Zeit das Objekt gelernt hat; Ich sehe viele Leute, die frisch in die Sprache kommen oder die sie sogar schon seit Jahren schreiben, aber eindeutig nach dem iOS-Boom keine Ahnung haben, was das+new
bedeutet. Zweitens+new
wäre Apple , wie es sehr alt ist und seit den nächsten Tagen, ziemlich verrückt, es so zu ändern, dass alter Code kaputt geht, insbesondere wenn man bedenkt, dass ihre eigenen Codebasen wahrscheinlich damit übersät sind.new
Redewendung von Smalltalk stammt. Es wird auch in Ruby verwendet, und sowohl Objective-C als auch Ruby leiten einen Großteil ihrer Syntax und Konventionen von Smalltalk ab.Häufig müssen Sie Argumente an übergeben,
init
sodass Sie eine andere Methode verwenden, z[[SomeObject alloc] initWithString: @"Foo"]
. Wenn Sie es gewohnt sind, dies zu schreiben, gewöhnen Sie sich an, dies so zu tun, und dies[[SomeObject alloc] init]
kann natürlicher sein[SomeObject new]
.quelle
Eine kurze Antwort lautet:
quelle
Als Randnotiz verwende ich persönlich,
[Foo new]
wenn ich möchte, dass etwas in init ausgeführt wird, ohne den Rückgabewert irgendwo zu verwenden. Wenn Sie die Rückgabe von[[Foo alloc] init]
nirgendwo verwenden, erhalten Sie eine Warnung. Mehr oder weniger verwende ich als[Foo new]
Augenweide.quelle
Ich bin sehr spät dran, aber ich möchte erwähnen, dass das Neue in der Obj-C mit Swift-Welt tatsächlich unsicher ist. Swift erstellt nur dann eine Standard-Init-Methode, wenn Sie keinen anderen Initialisierer erstellen. Das Aufrufen einer neuen schnellen Klasse mit einem benutzerdefinierten Initialisierer führt zu einem Absturz. Wenn Sie alloc / init verwenden, beschwert sich der Compiler ordnungsgemäß darüber, dass init nicht vorhanden ist.
quelle
Wenn new den Job für Sie erledigt, wird Ihr Code auch geringfügig kleiner. Wenn Sie sonst anrufen würden
[[SomeClass alloc] init]
an vielen verschiedenen Stellen in Ihrem Code , erstellen Sie in der Implementierung von new - dh in der objc-Laufzeit - einen Hot Spot, der die Anzahl Ihrer Cache-Fehlschläge verringert.Nach meinem Verständnis, wenn Sie einen benutzerdefinierten Initialisierer verwenden müssen
[[SomeClass alloc] initCustom]
.Wenn nicht, verwenden Sie
[SomeClass new]
.quelle
init
und verwenden Sie sie.[[SomeClass alloc] init];
Wenn Sie Parameter benötigen, tun Sie dies niemals[[SomeClass alloc] initWith:...];
. Wenn Sie dieinit
Funktion mit einer benutzerdefinierten Implementierung überschreiben , können Sienew
beim Erstellen eines Objekts aufrufen , und die benutzerdefinierteinit
Implementierung wird weiterhin aufgerufen .