initialize 和 init 得区别
Objective-C中带有运行时间的好处是,它可以在你的程序运行的流程中进行参与。在Objective-C中,它包括检查是否一个对象可以处理特定的消息,如果不能处理,它就帮助你自动调用其他特定的方法去完成。
initialize不是init
运行时间的行为之一就是initialize。虽然看起来有点像大家常见的init,但是他们并不相同。
在程序运行过程中,它会在你程序中每个类调用一次initialize。这个调用的时间发生在你的类接收到消息之前,但是在它的超类接收到initialize之后。
举例:
Duck.h
#import <Foundation/Foundation.h>
@interface Duck : NSObject
@end
Duck.m
#import "Duck.h"
@implementation Duck
+ (void)initialize
{
NSLog(@"I'm %@ initialize!" ,[self class]);
}
- (instancetype)init
{
if (self = [super init])
{
NSLog(@"I,m Duck init!");
}
return self;
}
@end
测试:
Duck *duck1 = [[Duck alloc] init];
Duck *duck2 = [[Duck alloc] init];
Duck *duck3 = [[Duck alloc] init];
结果:
2016-04-12 15:49:43.747 InitializeAndInt[9444:748335] I'm Duck initialize!
2016-04-12 15:49:43.748 InitializeAndInt[9444:748335] I,m Duck init!
2016-04-12 15:49:43.748 InitializeAndInt[9444:748335] I,m Duck init!
2016-04-12 15:49:43.748 InitializeAndInt[9444:748335] I,m Duck init!
我们可以看到,虽然我们创建了3个Duck的实例,但是initialize仅仅被调用了一次。我们也可以看到,直到我们创建了一个Duck的实例,initialize才被调用。
但是如果Duck有一个子类的话,比如我们建一个Duck的子类叫做Chicken
Chicken.h
#import "Duck.h"
@interface Chicken : Duck
@end
Chicken.m
#import "Chicken.h"
@implementation Chicken
@end
结果:
2016-04-12 15:54:09.160 InitializeAndInt[9517:750847] I'm Duck initialize!
2016-04-12 15:54:09.161 InitializeAndInt[9517:750847] I,m Duck init!
2016-04-12 15:54:09.161 InitializeAndInt[9517:750847] I,m Duck init!
2016-04-12 15:54:09.161 InitializeAndInt[9517:750847] I,m Duck init!
2016-04-12 15:54:09.161 InitializeAndInt[9517:750847] I'm Chicken initialize!
2016-04-12 15:54:09.161 InitializeAndInt[9517:750847] I,m Duck init!
我们看到了4个Duck的init和2个Duck的initialize方法。这是怎么回事呢?
看来如果一个子类没有实现initialize方法,那么超类会调用这个方法两次,一次为自己,而一次为子类。