--存在继承关系时initialize和load的调用问题--
1,如果没有重写,子类会调用父类的+(void)initialize
示例代码一
@interface SuperClass : NSObjec
@end
@implementation SuperClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
@end
@interface ChildClass : SuperClass
@end
@implementation ChildClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
示例代码二
@interface SuperClass : NSObjec
@end
@implementation SuperClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
@end
@interface ChildClass : SuperClass
@end
@implementation ChildClass
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
示例代码一中
ChildClass继承自SuperClass
SuperClass重写了initialize方法
ChildClass重写了initialize和load方法
示例代码二中
ChildClass继承自SuperClass
SuperClass重写了initialize方法
ChildClass重写了load方法
现在我们在Xcode的项目中只简单的import这两个类,而不去使用它们。然后运行项目,获得下面的结果:
//示例代码一
SuperClass +[SuperClass initialize]
ChildClass +[SuperClass initialize]
ChildClass +[ChildClass load]
示例代码二
SuperClass +[SuperClass initialize]
ChildClass +[ChildClass initialize]
ChildClass +[ChildClass load]
根据打印结果,可以看出:
两段代码中,打印结果完全相同。但ChildClass中并没有重写initialize方法。
当ChildClass的load方法被运行时自动调用时,由于class方法的调用,触发initialize方法被自动调用。
示例代码一中,ChildClass并没有重写initialize 方法,此时,由打印结果可知,先调用了父类的initialize方法,然后由于存在继承,子类没有重写父类的initialize,所以子类会去调用父类的initialize方法。
示例代码二中,ChildClass重写了父类的initialize方法,但此时仍然会调用父类的initialize方法,然后调用子类的initialize方法。
结论:无论子类是否重写父类的initialize方法,当子类的initialize方法被调用之前,都会先调用一次父类的initialize方法(亮点:即便被子类重写,却依然会被自动调用,这点和普通意义的继承重写规则不同)。
注意:这种规则同样适用于继承关系不止两层的情况
2,如果没有重写,子类不会调用父类的+(void)load
示例代码一
@interface SuperClass : NSObjec
@end
@implementation SuperClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface ChildClass : SuperClass
@end
@implementation ChildClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
@end
示例代码二
@interface SuperClass : NSObjec
@end
@implementation SuperClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
@interface ChildClass : SuperClass
@end
@implementation ChildClass
+(void)initialize{
NSLog(@"%@ %s",[self class], __FUNCTION__);
}
+ (void) load {
NSLog(@"%@ %s", [self class], __FUNCTION__);
}
@end
示例代码一中
ChildClass继承自SuperClass
SuperClass重写了initialize和load方法
ChildClass重写了initialize方法
示例代码二中
ChildClass继承自SuperClass
SuperClass重写了initialize和load方法
ChildClass重写了initialize和load方法
现在我们在Xcode的项目中只简单的import这两个类,而不去使用它们。然后运行项目,获得下面的结果:
//示例代码一
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
示例代码二
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
ChildClass +[ChildClass initialize]
ChildClass +[ChildClass load]
根据打印结果,可以看出:
两段代码中,打印结果完全不相同。代码区别在于ChildClass是否有重写父类的load方法。
当父类的load方法被运行时自动调用时,由于class方法的调用,触发initialize方法被自动调用。
示例代码一中,ChildClass并没有重写load方法,此时,由打印结果可知,子类虽然继承于父类,但此时,子类并没有去执行父类的load方法。
示例代码二中,ChildClass重写了父类的load方法,此时运行时会调用子类重写的load方法,注意,此时并不影响父类的load方法的调用。
结论:当子类没有重写父类的load方法,子类被引用时运行时不会自动去调用父类的load的方法,即便子类有继承父类的load方法。当子类重写了父类的load方法后,子类被引用时运行时会调用子类的load方法,此时并不会影响父类的load方法的调用。
总结:在继承关系中,对于initialize和load方法,子类都会继承。如果父类和子类都被调用,父类的调用一定在子类之前。但:当子类的initialize方法被触发之前(不管是否重写),都会先调用父类的initialize方法,如果子类重写了initialize方法,则接下来调用子类的,如果没有重写,则接下来再次调用父类的initialize方法。而load方法则完全不同,首先,如果子类没有重写父类的load方法,则不会去调用父类的load方法,也就是说:对于一个类而言,没有load方法实现就不会调用,不会考虑对父类的继承。如果子类重写的父类的load方法,则在调用子类方法之前会自动调用父类的load方法,也就是说:一个类的load方法不用写明[super load],父类就会收到调用,并且在子类之前。
3,不需要显示使用super调用父类中的方法
当我们定义init方法时,我们总是需要使用super关键字来调用父类的方法,让父类也完成相同的操作。这是因为对对象的初始化过程,OC不像C++,C#那样会自动调用父类默认的构造函数。因此,我们总是需要将这个函数写成这样:
- (id)init{
self = [super init];
if (self) {
}
return self;
}
注:ARC模式下,dealloc不用再使用super调用父类的dealloc方法
但是initialize和load不需要使用super调用父类的方法。因为当子类的load被调用时,Runtime会自动对父类的load方法进行调用,而initialize则会随子类自动激发父类的方法,同时,当子类激活继承下来的父类方法时,如果父类的方法中用到了self,其指代的依然是子类自身,而不是父类。这是OC区别于C++,Java等面向对象语言的地方:类方法也有多态性。
资料链接:
[IDER]:
http://blog.iderzheng.com
http://blog.iderzheng.com/objective-c-load-vs-initialize/
[MrPeak杂货铺]:http://blog.csdn.net/hanangellove/article/details/45033453
[知乎上的一个怎么面试iOS工程师的问题]:
http://blog.csdn.net/hanangellove/article/details/45033453