5

Cocoa フレームワークには、新しいインスタンスが返される可能性があるため、継承されたクラスself = [super init]のメソッドで常に呼び出すという規則があります。init[super init]

これを行うとどうなりますか?

@interface MyClass : NSObject /* or any other class */ {
    int ivar_;
}
@end

@implementation MyClass

- (id)init {
    ivar_ = 12345;

    if ((self = [super init])) {
        NSLog(@"ivar_'s value is %d", ivar_);
    }
    return self;
}

@end

when[super init]が新しいインスタンスを返す場合、コンソールには何が表示されますか? ivar_'s value is 0?

どのクラスがそのメソッドから新しいインスタンスを返す可能性があるのか​​ わからないため、これを自分で確認する方法は考えられませんinit。また、ドキュメントでこのシナリオの明示的な説明が見つからないようです。

誰か助けてくれませんか?ありがとう!

4

1 に答える 1

5

通常の状況では+alloc、クラスに送信すると、そのクラスのゼロ化されたインスタンスが返されます。これは、a) そのクラスの適切なインスタンスであり、b) すべてのインスタンス変数がゼロに設定されている (数値型は 0、C ポインターは NULL、オブジェクトは nil など) という意味で、既に初期化されています。ただし、新しく作成されたインスタンスに追加の初期化動作は適用されていません-init。これは、最も一般的な初期化子の仕事です。特に、クラスがから継承する場合NSObject[super init]新しく作成されたインスタンスには触れません。したがって、質問に投稿したコードでは、

  1. (クラス外)+allocが に送信されMyClass、ゼロに設定されたインスタンスが返されます。特にivar_は 0
  2. (クラス外)-init新しく作成されたインスタンスに送信されます
  3. ivar_ == 12345の代入のため、-initとして書き換えることができますself->ivar_ = 12345。この時点で、selfによって返されたインスタンスを指します+alloc
  4. [super init]が送信され、ivar_そのスーパークラス ( NSObject) がそれを認識していないため変更されず、戻り値が に割り当てられselfます。実際、戻り値はすでに変更されていselfないため、何も変更されていません
  5. selfは とは異なるためnilNSLog()と呼ばれます
  6. -init戻り値self

[super init]が返すインスタンスとは異なるインスタンスを返すと考えてみましょう+alloc:

  1. (クラス外)+allocが に送信されMyClass、ゼロに設定されたインスタンスが返されます。特にivar_は 0
  2. (クラス外)-init新しく作成されたインスタンスに送信されます
  3. ivar_ == 12345の代入のため、-initとして書き換えることができますself->ivar_ = 12345。この時点で、selfによって返されたインスタンスを指します+alloc
  4. [super init]が送信され、現在のインスタンスを解放して別のインスタンスを返すことを決定します。戻り値が割り当てられてselfいるため、現在の観点から-initは、別のインスタンスで作業しています。古いインスタンスの割り当てが解除されたため、その変更ivar_は失われます。含める必要があると判断したものをivar_含む[super init]
  5. selfは とは異なるためnilNSLog()と呼ばれます
  6. -initを返しますself。これは、によって作成されたインスタンスと同じではありません。+alloc

これは、次のコードでテストできます。これは私の答えを説明するための簡単な例であり、実稼働コードでは使用しないでください。

#import <Foundation/Foundation.h>

@interface MySuperClass : NSObject
@end

@interface MyClass : MySuperClass
{
  @public
  int ivar_;
}
@end

@implementation MySuperClass

static MyClass *defaultInstance;

- (id)init
{
  if ([self isMemberOfClass:[MyClass class]] && defaultInstance != nil)
  {
    [self release];
    return defaultInstance;
  }

  return [super init];
}
@end

@implementation MyClass
- (id)init
{
  ivar_ = 12345;

  if ((self = [super init]))
    NSLog(@"ivar_'s value is %d", ivar_);

  return self;
}
@end

int main()
{
  NSAutoreleasePool *pool = [NSAutoreleasePool new];

  defaultInstance = nil;
  defaultInstance = [[MyClass alloc] init];
  NSLog(@"%d", defaultInstance->ivar_); // outputs 12345

  defaultInstance->ivar_ = 98765;
  NSLog(@"%d", defaultInstance->ivar_); // outputs 98765

  MyClass *someInstance = [[MyClass alloc] init];
  NSLog(@"%d", someInstance->ivar_); // outputs 98765

  if (someInstance == defaultInstance)
    NSLog(@"They're the same!");

  [pool drain];
  return 0;
}

出力は

ivar_'s value is 12345
12345
98765
ivar_'s value is 98765
98765
They're the same!
于 2011-01-15T14:40:21.393 に答える