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

[super init]返回新实例的情况下,我会在控制台中看到什么?ivar_'s value is 0?

我自己想不出办法来检查这个,因为我不知道哪个类可以从它的init方法返回一个新实例。此外,似乎无法在文档中找到对这种情况的明确说明。

谁能帮帮我?谢谢!

4

1 回答 1

5

在正常情况下,当您发送+alloc到一个类时,它会返回该类的归零实例。它已经在以下意义上进行了初始化:a)它是该类的正确实例,并且 b)所有实例变量都被清零(数字类型为 0,C 指针为 NULL,对象为 nil 等)。但是,没有对新创建的实例应用额外的初始化行为——这是初始化器的工作,-init是其中最常见的。特别是,如果您的类从NSObjectthen继承,则[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 回答