2

Objective-C の新機能。init メカニズムをよりよく理解するためにコード スニペットを作成し、いくつかの質問に行き着きました。

@implementation MyClass    
    -(id) init
    {
        if (self) {
            i = 5;
            NSLog(@"self before init - %@ %p i=%d",[self className], &self, i);
        } else {
            NSLog(@"self is null???");
        }

        id someClass = [super init];
        NSLog(@"the result of super-init - %@ %p",[someClass className], &someClass);

        self = [super init];
        if (self) {
            NSLog(@"self after init - %@ %p %d",[self className], &self, i);
        } else {
            NSLog(@"self is null???");
        }

        return self;
    }

iプライベート インスタンス変数ですint

結果は次のとおりです。

2012-12-14 18:01:26.403 Init[1621:303] self before init - MyClass 0x7fff5fbff848 i=5
2012-12-14 18:01:26.405 Init[1621:303] the result of super-init - MyClass 0x7fff5fbff838
2012-12-14 18:01:26.405 Init[1621:303] self after init - MyClass 0x7fff5fbff848 5

本当に驚いたのは、someClass のクラス名がMyClass.

  • NSObjectサブクラスのインスタンスを返すことをどのように知っていますか (型が一致するだけでなく、まったく同じオブジェクトです)。

init何度も呼び出して、呼び出す前にインスタンス変数を初期化するのは良い形ではないことは承知していますinitが、実験しているだけです。

ありがとう。

4

1 に答える 1

2

標準スキームを使用する必要があります(多かれ少なかれ):

-(id)init {
    self = [super init];
    if (self) {
        // Do initialization stuff
    }
 }

あなたのクラスは他のクラスをサブクラス化します。への呼び出しsuper initは、スーパークラスの init ルーチンを実行します。これがないと、クラスが適切に初期化されず、奇妙に誤動作する可能性があります。super init(しかし、これは悪い副作用をもたらす可能性があるため、おそらく 2 回呼び出すのは賢明ではありません。)

を呼び出さずに、独自のクラスでsuper initのバージョンを呼び出す場合があります。init基本的に、 と がある場合はinitWithJunk:、の代わりにcallを使用してinit、実行することを実行し、 で再現する必要がないようにすることができます。initWithJunk:[self init][super init]self initinitWithJunk:

これは、既存のクラスにメソッドを追加する「カテゴリ」を作成する場合に特に重要です。基本クラスの初期化子が確実に実行されるように、init...何らかのバージョンを呼び出す必要があります。[self init]

super initこのメソッドは (通常)既存のインスタンスを新しいインスタンスに置き換えるのではなくスーパークラスに属するインスタンス フィールドを初期化することを理解してください。super init呼び出しから "self" 値を受け取る理由は 2 つあります。

  1. nilinit ルーチンは、何らかのエラーが発生した場合に を返すことができます。
  2. いくつかの (まれな) 特殊なケースでは、init ルーチンが提供されたインスタンスを別のもの (たとえば、キャッシュされたバージョン) に置き換えることがあります。
于 2012-12-15T02:33:34.107 に答える