newの代わりにalloc initを使用


344

Objective-Cを学び、サンプルコードを読むと、オブジェクトは通常、このメソッドを使用して作成されていることがわかります。

SomeObject *myObject = [[SomeObject alloc] init];

の代わりに:

SomeObject *myObject = [SomeObject new];

私はそれらが同等であると読んだので、これには理由がありますか?


12
それが可能かどうかさえ知りませんでした!私が読んだすべての資料は、新しいキーワードが存在しないように見せかけています。
ジョナサン

78
実際、「new」はObjective-Cのキーワードではありませんが、NSObjectは、「alloc」と「init」を呼び出すだけのクラスメソッド「new」を実装しています。
Don McCaughey、

3
ジョナサン、まさにそれが私の質問のきっかけになりました。それらは機能的には同等ですが、[[alloc] init]が明らかに主要なイディオムです。
willc2 2009

1
Apple(iTunesスタンフォードの講義の1つで覚えていることから)は、代わりにalloc initを使用して、何が起こっているのかを理解できるようになっていると思います。また、サンプルコードではnewをあまり使用していないため、alloc initはAppleが宣伝しようとしている一般的な良い習慣のようです。
PostCodeism 2017

回答:


290

ここには多くの理由があります:http : //macresearch.org/difference-between-alloc-init-and-new

選択されたものは次のとおりです。

  • newカスタム初期化子(などinitWithString)をサポートしていません
  • alloc-init より明確です new

一般的な意見としては、使い慣れたものを使用する必要があるようです。


8
クラスが指定された初期化子として-initを使用する場合、+ newはそれを呼び出します。Jeremyが言及しているのは、-initではないカスタム初期化子がある場合です。-initWithName:など。
bbum

87
+newWithString:すでに実装して-initWithStringいる場合でも、実装を妨げるものは何もありません。それほど一般的ではありません。個人的にnewinit、指定されたイニシャライザがの場合は常に使用しています。
PeyloW 2009

11
これは古いスレッドであることは知っていますが、実装すべきではないことを強調したいだけです+newWithString:。それは懸念の分離を壊します。-initとにかく使いたいだけの場合は、を使わない理由はありません+new
ジョナサンスターリング

7
@JonathanSterling:Appleは、あなたが忠告していることを正確に実行しているように見える多くのインスタンスを持っています。たとえば[[NSString alloc] initWithFormat:...][NSString stringWithFormat:...]は両方とも同等です。Appleは懸念の分離に違反していて、このように実装すべきではないと言っていませんか?(注:私は軽蔑するつもりはありません。詳細を知りたいのですが、Appleのリードに従うのが悪い考えであるかどうかを知りたいと思います。)
2013年

6
@Senseful ARC(またはガベージコレクション)の前の日付に遡ると思います。これらの2つは同等ではありません。stringWithFormat:は自動解放された文字列を返しますが、alloc:init:は手動で解放または自動解放する必要があります。そうしないと、メモリリークが発生します。
msfeldstein 2014

139

非常に古い質問ですが、楽しみのためにいくつかの例を書きました—多分あなたはそれが役に立つと思うでしょう;)

#import "InitAllocNewTest.h"

@implementation InitAllocNewTest

+(id)alloc{
    NSLog(@"Allocating...");
    return [super alloc];
}

-(id)init{
    NSLog(@"Initializing...");
    return [super init];
}

@end

メイン関数で両方のステートメント:

[[InitAllocNewTest alloc] init];

そして

[InitAllocNewTest new];

同じ出力になります:

2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating...
2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...

5
正解です。ただ、+は、新しい使用して、あなただけより-initWithSomethingのような専門-initを使用する必要がないと何も例のための偉大であることを追加したい:...
cgossain

残念ながら、この例はそれらが同一であることの証明ではありません。同じ結果が得られる例にすぎません。
Vince O'Sullivan、2014年

10
残念ながら、この例はそれらが同一であることの証明ではありません。これは、同じ結果が得られる例にすぎません。一方、これはそれらが異なることを証明します...上記の例で、 "InitAllocNewTest.h"を次のように変更します。@interface InitAllocNewTest:NSObject-(instancetype)__unavailable init; @end は影響を受けませ[[InitAllocNewTest alloc] init]んがコンパイルされ[InitAllocNewTest new]ません。(改行の欠如などの謝罪)
Vince O'Sullivan

1
@ VinceO'Sullivan、良い点。つまり、シングルトンクラスのようにinitを使用不可にしたい場合は、newも無効にする必要があります。シングルトンが良いか悪いかについてはここでは触れません。
user3099609 2015年

上記のコードから質問があります。なぜ「[super init]を返す」のですか?一般的にinitはクラスのメンバーが初期化されるメソッドであり、ポインターの変更が非常に奇妙です!
Pruthvidhar Rao Nadunooru 16

52

+new+alloc/-initAppleのNSObject実装と同等です。これが変更される可能性はほとんどありませんが、あなたのパラノイアレベルによっては、Appleのドキュメント+newが将来の実装の変更(および同等性の破壊)を可能にするようです。このため、「明示的なものは暗黙的なものよりも優れている」ため、歴史的な継続性のため、Objective-Cコミュニティは一般的にを避けてい+newます。ただし、通常、Objective-Cへの最近のJavaの参入者は、を使いこなすことで見つけることができ+newます。


8
これはしばしば真実ですが、簡潔さを支持する陣営もあります。その場合、それを保証する明確かつ現在の懸念がある場合にのみ、より明確になります。
Peter DeWeese

27
私はこれを否定しました+new。なぜなら、NeXTの時代から存在していたからです。+new何かがずっと前にobjcを学んだ誰かのしるしであるなら、この言語に慣れた人、あるいは何年も書いてきたが、iOSブームの後に明らかにそれを理解している多くの人が、どういう+new意味か分からないようです。第2に、+new非常に古く、次の時代から、Appleは古いコードを壊すような方法で変更するのは非常に気が狂います。
asveikau

1
newイディオムはSmalltalkから来ていると確信しています。Rubyでも使用されており、Objective-CとRubyの両方は、Smalltalkから多くの構文と規則を派生させています。
Brendon Roberto

3
割り当ての変更のみが可能です。ドキュメントは明示的に-initが呼び出されると述べています。したがって、これはallocをオーバーライドするかどうかによります。
Kendall Helmstetter Gelner 2014

7
特にキーストロークを保存することで時間を節約できるObjective-Cのような冗長な言語では、MOREを入力する必要があるソリューション(alloc init)が好ましい理由は本当に想像できません。それらの「賢明なJava開発者」は、同じ機能の結果を生み出す余分な文字を不必要に入力する代わりに、分析スキルを使用してコードの作成に費やす時間を短縮しています。
DiscDev 2014年

9

多くの場合、引数を渡す必要があるinitため、などの別のメソッドを使用し[[SomeObject alloc] initWithString: @"Foo"]ます。あなたがこれを書くことに慣れているなら、あなたはこのように書く習慣を身につけるので、[[SomeObject alloc] init]より自然に来るかもしれません[SomeObject new]


7

短い回答者は次のとおりです。

  1. どちらも同じです。だが
  2. 'new'は基本的な 'init'イニシャライザでのみ機能し、他のイニシャライザ(たとえば、initWithString :)では機能しません。

3

[Foo new]余談ですが、個人的には、戻り値をどこでも使用せずに何かをinitで実行したい場合に使用します。[[Foo alloc] init]どこでもリターンを使用しない場合、警告が表示されます。多かれ少なかれ、私は[Foo new]目の保養に使用します。


3

私はこれに非常に遅れていますが、Obj-C with Swiftの世界では、その新しいものは実際には安全ではないことを述べておきたいと思います。他の初期化子を作成しない場合、Swiftはデフォルトのinitメソッドのみを作成します。カスタム初期化子を使用してSwiftクラスでnewを呼び出すと、クラッシュが発生します。alloc / initを使用すると、コンパイラーはinitが存在しないことを正しく報告します。


1

newがあなたのために仕事をするなら、それはあなたのコードを適度に小さくします。それ以外の方法で[[SomeClass alloc] init]コード内のさまざまな場所で呼び出す場合は、新しい実装、つまりobjcランタイムでホットスポットを作成し、キャッシュミスの数を減らします。

私の理解では、カスタム初期化子を使用する必要がある場合 [[SomeClass alloc] initCustom]

そうでない場合は、を使用してください[SomeClass new]


1
「カスタム初期化子を使用する必要がある場合は、[[SomeClass alloc] initCustom]を使用する」と主張します。パラメータなしのカスタム初期化子が必要な場合は、提案されているようなことはせず、デフォルトのinit関数をオーバーライドして使用し[[SomeClass alloc] init];ます。パラメータが必要な場合でも、そのようなことをしないでください[[SomeClass alloc] initWith:...];。最後に、init関数をカスタム実装でオーバーライドする場合new、オブジェクトの作成時に呼び出すことができますが、それでもカスタムinit実装が呼び出されます。
dirtydanee 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.