Objective c 目标从头算

Objective c 目标从头算,objective-c,inheritance,objective-c-runtime,Objective C,Inheritance,Objective C Runtime,免责声明,我不熟悉目标C。但我找不到解释。我看到了两种实现init的方法: - (id)init { if ([super init]) { return self; } else { return nill; } } 及 假设我有: myObj = [[MyObject alloc] init]; 其中MyObject类是NSObject的子类。在第二个示例中,init是否不返回NSObject的初始化版本?所以myObj会。。。它怎么知道它是什么?难道它不

免责声明,我不熟悉目标C。但我找不到解释。我看到了两种实现init的方法:

- (id)init {

  if ([super init]) {
    return self;
  } else {
    return nill;
  }

}

假设我有:

myObj = [[MyObject alloc] init];
其中MyObject类是NSObject的子类。在第二个示例中,init是否不返回NSObject的初始化版本?所以myObj会。。。它怎么知道它是什么?难道它不认为它是一个NSObject而不是一个MyObject吗?

1)第一个版本就错了
self
应始终使用
super
初始值设定项返回的值进行赋值,因为
super
init
可以在初始化时返回另一个对象(顺便说一句,这并不罕见)。第二个版本实际上是实现
init
方法的“官方”方式

2) “它不会认为这是一个NSObject而不是一个MyObject”。myObj是“NSObject”的实例和“MyObject”的实例。这就是继承的全部意义。

1)第一个版本就是错的
self
应始终使用
super
初始值设定项返回的值进行赋值,因为
super
init
可以在初始化时返回另一个对象(顺便说一句,这并不罕见)。第二个版本实际上是实现
init
方法的“官方”方式

2) “它不会认为这是一个NSObject而不是一个MyObject”。myObj是“NSObject”的实例和“MyObject”的实例。这就是继承的全部意义

我只是想知道,在引擎盖下,它是如何做到的

这很简单。您将要编写的所有类中99.9%将以某种方式从
NSObject
继承。在初始值设定项中,您应该调用
super
的指定初始值设定项并将其分配给
self
。最终,
[super init]
将调用
-[NSObject init]
,实现方式如下:

- (id)init {
    return self;
}
- (id) initWithFoo:(id)aFoo {
  if ([aFoo isSuperFast]) {
    [self release];
    return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
  }
  self = [super init];
  if (self) {
    _foo = [aFoo retain];
  }
}
因此,从技术上讲,如果您直接从
NSObject
继承,那么您可能不会进行
self=[super init]的赋值,因为您知道(并且您得到保证)这相当于:
self=self,这有点毫无意义。无论如何,为了保持一致性,您应该保留它

然而,一旦你开始在继承链上走得更远,特别是当你从不透明类(即,一个你没有.m文件的类)继承时,事情就开始变得不明朗了。您可能会遇到一个类,其指定的初始值设定项如下所示:

- (id)init {
    return self;
}
- (id) initWithFoo:(id)aFoo {
  if ([aFoo isSuperFast]) {
    [self release];
    return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
  }
  self = [super init];
  if (self) {
    _foo = [aFoo retain];
  }
}
这并不常见,但确实发生过。在本例中,我们正在销毁
self
[self release]
,以平衡紧跟在此之前的
alloc
调用)并返回另一个对象

我只是想知道,在引擎盖下,它是如何做到的

这很简单。您将要编写的所有类中99.9%将以某种方式从
NSObject
继承。在初始值设定项中,您应该调用
super
的指定初始值设定项并将其分配给
self
。最终,
[super init]
将调用
-[NSObject init]
,实现方式如下:

- (id)init {
    return self;
}
- (id) initWithFoo:(id)aFoo {
  if ([aFoo isSuperFast]) {
    [self release];
    return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
  }
  self = [super init];
  if (self) {
    _foo = [aFoo retain];
  }
}
因此,从技术上讲,如果您直接从
NSObject
继承,那么您可能不会进行
self=[super init]的赋值,因为您知道(并且您得到保证)这相当于:
self=self,这有点毫无意义。无论如何,为了保持一致性,您应该保留它

然而,一旦你开始在继承链上走得更远,特别是当你从不透明类(即,一个你没有.m文件的类)继承时,事情就开始变得不明朗了。您可能会遇到一个类,其指定的初始值设定项如下所示:

- (id)init {
    return self;
}
- (id) initWithFoo:(id)aFoo {
  if ([aFoo isSuperFast]) {
    [self release];
    return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
  }
  self = [super init];
  if (self) {
    _foo = [aFoo retain];
  }
}

这并不常见,但确实发生过。在这种情况下,我们正在销毁
self
[self release]
,以平衡前面的
alloc
调用),而是返回一个不同的对象。

对,我理解。我是说我知道它的作用。我只是想知道,在引擎盖下,它是如何做到的。NSObject类的对象不会具有MyObject类的对象所具有的属性或方法。我希望NSObject的init返回一个NSObject。从语法上讲,这让我很困惑。-init返回一个id,而不是NSObject*@scriptThis:我明白了。但创建对象的不是
init
,而是
alloc
,因为
alloc
被发送到
MyObject
类,它将返回
MyObject
实例。通常,
[super init]
将设置对象的超类部分(在您的示例中为“NSObject”),仅此而已。如果
[super init]
希望放弃当前实例并返回另一个实例,则它有责任返回“MyObject”实例或其子类的实例。要做到这一点并不容易,但框架类可以做到这一点。@hoha:super的init知道是谁调用的吗?知道那是我的一个孩子。。。并返回一个MyObject对象,或者一个名为init的任何类型的对象@NSResponder,是的,init被定义为返回id,但我相信id可以保存任何类型的对象(同样,我知道,所以…),在本例中,它是MyObject类的对象。对,我理解它。我是说我知道它的作用。我只是想知道,在引擎盖下,它是如何做到的。NSObject类的对象不会具有MyObject类的对象所具有的属性或方法。我希望NSObject的init返回一个NSObject。从语法上讲,这让我很困惑。-init返回一个id,而不是NSObject*@scriptThis:我明白了。但创建对象的不是
init
,而是
alloc
,因为
alloc
被发送到
MyObject
类,它将返回
MyObject
实例。通常
[super init]
将在ca中设置对象的超类部分(“NSObject”)