init
オブジェクトの割り当て後に呼び出す必要は本当にありますか? つまり、たとえばJavaでは、それを呼び出さない場合(コンストラクター)、とにかく呼び出されます(デフォルトのコンストラクター)。Objective C では、別のコンストラクタ (Java など) を作成できます。私が最もよく目にするものの 1 つはself = [super init]
. cocoawithlove の記事を読みましたが、結局のところ、なぜそのような割り当てを行う必要があるのか は明確ではありませんself = [super init]
。[super init]
は別のオブジェクトを返すことができると言っているだけなので、self
をその新しいオブジェクトに置き換える必要があります。そもそもなぜそれを行うのか説明できません。
3 に答える
オブジェクトの割り当て後に init を呼び出す必要は本当にありますか?
はい、必要です。Java と比較すると、[super init]
(または他の指定されたイニシャライザ) を呼び出すと、スーパークラスのコンストラクタが効果的に実行されます。このメカニズムは Java で提供されていますが、Objective-C では提供されていません。したがって、Java のように ObjC で暗黙的に呼び出されることはありません。ObjC では、スーパークラスの指定された初期化子の 1 つを明示的に呼び出す必要があります。スーパークラスの初期化子を呼び出さない場合、オブジェクトは完全には初期化されません。これにより、副作用がまったく発生しないか、未定義の動作を引き起こす完全に使用できないオブジェクトになる可能性があります。
なぜそのような代入をするべきなのか self = [super init].
そうです、割り当てをalloc
作成し(メモリをゼロにして)、ポインターをクラス情報に設定しますisa
が、スーパークラスの初期化子により、スーパークラスがインスタンスを別のインスタンスと交換することが許可されます。通常、独自のサブクラスでこれを行うことは避けます。これと nil チェックを実行するもう 1 つの理由は、エラーを処理する手段だからです。ObjC では、例外は一般に回復不可能であるため、サブクラスにエラーを報告する従来の方法は、 を返すことnil
です。そのため、 を割り当てるだけself
でなく、 をテストすることも重要ですnil
。
Objective C と Java には大きな違いがあります。Java はゼロから構築されたインタープリター言語であり、Objective C は C 言語の上に構築されました。C でできることはすべて、Objective C でも有効です。
Java とは異なり、C (ひいては Objective C) には「生のメモリ割り当て」があります。Java では、 を呼び出すと、コンストラクターがnew
自動的に呼び出されます。この言語は、このメカニズムを回避することを不可能にします。ただし、Objective C では生メモリを割り当てることができます。メモリが返却された時点では、すぐに使用できるオブジェクトは含まれていませんalloc
。部分的に使用できる状態になっているだけです。メモリ ブロックには参照カウントがあり、オブジェクトに適合する十分なスペースを提供しますが、独自のサブクラスが実装したメッセージを受信する準備ができていません。そのため、 を呼び出すinit
(または と を組み合わせた を使用する)new
必要があります。alloc
init
割り当て/チェックにより、if (self = [super init])
オブジェクトの構築段階でエラーをトラップできます。独自のイニシャライザが失敗した場合はself = nil
、チェーンの上流に問題を報告するように設定できます。別のオブジェクトを割り当てることはあまり一般的ではありませんが、同様に行うことができます。
割り当て後、インスタンス変数をインスタンス化する必要があります。
self = [super init]
スーパークラスのinitメソッドの初期化を参照
よくある間違いは、
self = [[super alloc] init];
これはスーパークラスのインスタンスを返しますが、これはサブクラスのコンストラクター/init で必要なものではありません。サブクラスのメソッドに応答しないオブジェクトが返され、混乱を招く可能性があり、メソッドに応答しない、または識別子が見つからないなどの紛らわしいエラーが生成されます。
self = [super init]
サブクラスのメンバーをセットアップする前に最初に初期化するメンバー (変数またはその他のオブジェクト) がスーパークラスにある場合に必要です。それ以外の場合、objc ランタイムはそれらをすべて 0 または nil に初期化します。(ANSI C とは異なり、メモリのチャンクをまったくクリアせずに割り当てることがよくあります)
もちろん、基本クラスの初期化は、メモリ不足エラー、コンポーネントの欠落、リソース取得の失敗などのために失敗する可能性があるため、nil のチェックは賢明であり、数ミリ秒もかかりません。