Objective-C中的对象初始化序列
Cocoa框架有一个约定,总是在继承类的Objective-C中的对象初始化序列,objective-c,init,Objective C,Init,Cocoa框架有一个约定,总是在继承类的init方法中调用self=[super init],因为[super init]可能会返回一个新实例 如果我这样做会发生什么 @interface MyClass : NSObject /* or any other class */ { int ivar_; } @end @implementation MyClass - (id)init { ivar_ = 12345; if ((self = [super init]
init
方法中调用self=[super 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的值为0
我自己想不出一种方法来检查这一点,因为我不知道哪个类可以从它的init
方法返回一个新实例。此外,在文档中似乎找不到对此场景的明确说明
有人能帮我吗?谢谢 在正常情况下,当您向一个类发送
+alloc
时,它将返回该类的一个调零实例。它已经初始化为:a)它是该类的适当实例,b)所有实例变量都被调零(数值类型为0,C指针为NULL,对象为nil,等等)。但是,没有对新创建的实例应用额外的初始化行为-这是初始化器的工作,-init
是其中最常见的。特别是,如果类继承自NSObject
,则[super init]
不会触及新创建的实例。所以,在你在问题中发布的代码中
+alloc
被发送到MyClass
,它返回一个调零的实例。特别是,ivar\uu
为0-init
被发送到新创建的实例ivar_==12345
,因为-init
中的赋值可以重写为self->ivar_==12345
。此时,self
指向+alloc
返回的实例[super init]
被发送时,ivar\uuu
不会被触摸,因为它的超类(NSObject
)不知道它,返回值被分配给self
。事实上,返回值已经是self,因此没有任何更改self
与nil
不同,因此调用了NSLog()
-init
返回self
现在让我们考虑<代码> [Super init ] < /Calp>返回一个与“代码> + OLC/<代码>返回的实例不同的实例:
+alloc
被发送到MyClass
,它返回一个调零的实例。特别是,ivar\uu
为0-init
被发送到新创建的实例ivar_==12345
,因为-init
中的赋值可以重写为self->ivar_==12345
。此时,self
指向+alloc
返回的实例[super init]
被发送,它决定释放当前实例并返回另一个实例。返回值被分配给self
,因此,从当前的角度来看,-init
正在另一个实例上工作。旧实例已被解除分配,因此对ivar\uu
的更改将丢失ivar\uu
包含[super init]
决定它应该包含的内容self
与nil
不同,因此调用了NSLog()
-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;
}
我明白你的意思。现在我在考虑它,我意识到
[super init]
不陷入无限递归就无法返回新创建的实例。如果我错了,请告诉我。无论如何,我现在已经清楚地知道了这个问题的答案:self=[super init]
必须是任何init方法的第一行,即使文档中没有明确说明。感谢您的示例代码。是的,您不能简单地分配一个新实例,因为这将产生无限递归。是的,self=[super init]
(或-init
的变体)应该是任何普通初始化器的第一行,因为不能保证[super init]
返回相同的实例。如果是这样,将[super init]
的返回值指定给self
就没有意义了。我误解了你的问题。所以删除了我的答案。从技术上讲,init可以返回不同类的实例。我以为你在问这个。
ivar_'s value is 12345
12345
98765
ivar_'s value is 98765
98765
They're the same!