2

新的objective-c。写了一个代码片段来更好地理解初始化机制,最后问了几个问题。

@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,因为这可能会产生不良的副作用。)

在某些情况下,您不会调用super init,而是会init在您自己的类中调用 的版本。基本上,如果你有initWithJunk:and init,你可以用initWithJunk:call[self init]代替,[super init]这样self init会做的事情就可以完成并且不必在initWithJunk:.

如果您编写一个将init...方法添加到现有类的“类别”,这一点尤其重要——您必须调用某个版本[self init]以确保基类的初始化程序运行。

了解该super init方法不是(通常)用新实例替换现有实例,而是初始化其中属于超类的实例字段。从super init调用中接收“self”值的原因有两个:

  1. nil如果发生某种错误,init 例程可以返回 a 。
  2. 在一些(罕见的)特殊情况下,init 例程可能会用不同的实例(例如,缓存版本)替换提供的实例。
于 2012-12-15T02:33:34.107 回答