Stephen Kochan の本 "Programming in Objective-C" - 第 4 版の次の内容を理解するのに苦労しています。ご理解いただけると幸いです。
第 10 章の「オブジェクトの初期化」セクションで、Stephen は次のように書いています。
イニシャライザを記述するときは、次の 2 つの戦略に従う必要があります。
クラス内のオブジェクトの 1 つが初期化されるたびに、何か特別なことをしたい場合があります。たとえば、クラスが使用し、1 つ以上のインスタンス変数を介して参照するオブジェクトを作成するのに最適な場所です。その完璧な例は、Rectangle クラスです。init メソッドで四角形の XYPoint 原点を割り当てるのが合理的です。そのためには、継承された init メソッドをオーバーライドするだけです。
init をオーバーライドするために使用される標準の「テンプレート」があり、次のようになります。
- (id) init
{
self = [super init];
if (self) {
// initialisation code here.
}
return self;
}
このメソッドは、最初に親初期化子を呼び出します。親の初期化子を実行すると、継承されたインスタンス変数が適切に初期化されます。
親の init メソッドを実行した結果を自分自身に割り当てる必要があります。初期化子にはメモリ内のオブジェクトの場所を変更する権利があるためです (つまり、その参照が変更されます)。
親の初期化子が成功した場合、返される値は、if ステートメントでテストされているように非 nil になります。コメントが示すように、次のブロック内に、オブジェクトの独自のカスタム コードを配置できます。これには、多くの場合、クラスにあるインスタンス変数の割り当てと初期化が含まれます。
OK、これまでのところ、Stephen Kochan が言おうとしていることは理解できましたが、次の部分では完全に当惑しています。お役に立てれば幸いです。
クラスに複数の初期化子が含まれている場合、そのうちの 1 つを指定された初期化子にし、他のすべての初期化メソッドでそれを使用する必要があります。通常、これは最も複雑な初期化方法です (通常、最も多くの引数を取る方法です)。
したがって、私の最初の質問は次のとおりです。この場合、「指定された」イニシャライザをすべて使用する場合、他のすべての初期化メソッドがあるのはなぜですか?
Stephen Kochan 氏は次のように続けています。
指定された初期化子を作成すると、メインの初期化コードが 1 つのメソッドに集約されます。クラスをサブクラス化する人は誰でも、指定された初期化子をオーバーライドして、新しいインスタンスが適切に初期化されるようにすることができます。
この例を挙げていただけますか?彼の言っていることが理解できたのかよくわからない.
スティーブンは続けます:
その議論に基づいて、 Fraction クラスの初期化メソッド initWith:over: は次のようになります。
- (Fraction *) initWith:(int)n over:(int)d
{
self = [super init];
if (self) {
[self setTo: n over: d];
}
return self;
}
super の初期化 (およびその成功は、ゼロ以外の値の戻りによって示される) に続いて、
setTo:over:
メソッドを使用して Fraction の分子と分母を設定します。他の初期化メソッドと同様に、ここで行う初期化されたオブジェクトを返すことが期待されています。
initWith:over:
プログラム 10.1 は、新しい初期化方法をテストします。
#import "Fraction.h"
int main (int argc, char *argv[])
{
@autoreleasepool {
Fraction *a, *b;
a = [[Fraction alloc] initWith: 1 over: 3];
b = [[Fraction alloc] initWith: 3 over: 7];
[a print];
[b print];
}
return 0;
}
出力:
1/3
3/7
これまでのところ、コードを理解しました。次の部分がまったくわかりません。
指定されたイニシャライザについて前述した規則に従うには、 Fraction クラスの init も変更する必要があります。クラスがサブクラス化される可能性がある場合、これは特に重要です。
init メソッドは次のようになります。
- (id)init
{
return [self initWith:0 over:0];
}
サブクラス化する場合、なぜこれが重要なのですか?
スティーブン・コーチャンは次のように続けます。
プログラムが実行を開始すると、初期化呼び出しメソッドがすべてのクラスに送信されます。クラスと関連するサブクラスがある場合、親クラスが最初にメッセージを取得します。このメッセージは各クラスに 1 回だけ送信され、他のメッセージがクラスに送信される前に送信されることが保証されます。その目的は、その時点でクラスの初期化を実行することです。たとえば、その時点でそのクラスに関連付けられているいくつかの静的変数を初期化したい場合があります。
この最後の部分もよくわかりませんでした。お役に立てれば幸いです。