刨根问底:对于 self = [super init] 的思考
2016-03-29 11:34
267 查看
原文出处: Martin_wjl(@Martin_wjl)
转载自 伯乐在线
对象初始化有两种方式:
对于后者,有分配和初始化的过程,
一般不推荐使用
+ new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
//而 alloc/init 像这样:
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{
return self;
}
发现
{
if (self = [super init]) {
// Custom initialization
}
return self;
}
我们知道
但是对于
优先调用
那么
这里是担心父类初始化失败,如果初始化一个对象失败,就会返回
@implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
当调用
id objc_msgSend(id self, SEL op, ...)
这时候就开始了消息传递和转发的过程,会先从
对于
- (Class)class {
return object_getClass(self);
}
所以打印结果为
当调用
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
struct objc_super {
__unsafe_unretained id receiver;
__unsafe_unretained Class super_class;
};
结构体包含两个成员,第一个是
会发现不管是
深入理解Objective-C的Runtime机制
What exactly is super in Objective-C?
转载自 伯乐在线
对象初始化有两种方式:
[class new]与
[[class alloc] init]
对于后者,有分配和初始化的过程,
alloc从应用程序的虚拟地址空间上为该对象分配足够的内存,并且将新对象的引用计数加1、将对象的成员变量初始为零,
init会做真正的初使化工作,为对象的实例变量赋予合理有用的值。
一般不推荐使用
[class new],而推荐使用
[[class alloc] new],查看源码分析一下:
+ new
{
id newObject = (*_alloc)((Class)self, 0);
Class metaClass = self->isa;
if (class_getVersion(metaClass) > 1)
return [newObject init];
else
return newObject;
}
//而 alloc/init 像这样:
+ alloc
{
return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
- init
{
return self;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | + new { id newObject = (*_alloc)((Class)self, 0); Class metaClass = self->isa; if (class_getVersion(metaClass) > 1) return [newObject init]; else return newObject; } //而 alloc/init 像这样: + alloc { return (*_zoneAlloc)((Class)self, 0, malloc_default_zone()); } - init { return self; } |
[class new]默认调用
[newObject init]方法,那么我们无法使用自定义的初始化方法,多了更多的局限性。那么
[class alloc] init]会更方便, 当然
[class alloc] init]的设计也是由于历史的原因。
为啥这么写?
- (instancetype)init{
if (self = [super init]) {
// Custom initialization
}
return self;
}
1 2 3 4 5 6 7 | - (instancetype)init { if (self = [super init]) { // Custom initialization } return self; } |
alloc返回一个有效的未初始化的对象实例。对于
self是
alloc返回的指针,同时可以在所有的方法作用域内访问。
但是对于
super,它只是一个”编译器指示符”,告诉编译器在父类中搜索方法的实现。
优先调用
[super init]是为了使超类完成它们自己的初始化工作。
那么
if (self = [super init])又是做啥?
这里是担心父类初始化失败,如果初始化一个对象失败,就会返回
nil,当返回
nil的时候
self = [super init]测试的主体就不会再继续执行。如果不这样做,你可能会操作一个不可用的对象,它的行为是不可预测的,最终可能会导致你的程序崩溃。
理解 Self & Super
看到网上一道经典的题目:@implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
1 2 3 4 5 6 7 8 9 10 11 12 | @implementation Son : Father - (id)init { self = [super init]; if (self) { NSLog(@"%@", NSStringFromClass([self class])); NSLog(@"%@", NSStringFromClass([super class])); } return self; } @end |
self表示当前这个类的对象,而
super是一个编译器标示符,和
self指向同一个消息接受者。在本例中,无论是
[self class]还是
[super class],接受消息者都是
Son对象,但
super与
self不同的是,
self调用
class方法时,是在子类
Son中查找方法,而
super调用
class方法时,是在父类
Father中查找方法。
当调用
[self class]方法时,会转化为
objc_msgSend函数,这个函数定义如下:
id objc_msgSend(id self, SEL op, ...)
1 | id objc_msgSend(id self, SEL op, ...) |
Cache中查找方法,然后当前类,如果还是查找不到会去父类,直至
NSObject类
对于
NSObject类中,
- (Class)class的实现如下:
- (Class)class {
return object_getClass(self);
}
1 2 3 | - (Class)class { return object_getClass(self); } |
Son
当调用
[super class]方法时,会转化为
objc_msgSendSuper,这个函数定义如下:
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
1 | id objc_msgSendSuper(struct objc_super *super, SEL op, ...) |
objc_msgSendSuper函数第一个参数
super的数据类型是一个指向
objc_super的结构体
struct objc_super {
__unsafe_unretained id receiver;
__unsafe_unretained Class super_class;
};
1 2 3 4 | struct objc_super { __unsafe_unretained id receiver; __unsafe_unretained Class super_class; }; |
receiver,表示类的实例。第二个成员是记录当前类的父类是什么,会优先从
Father这个类里去找
- (Class)class,然后进行消息传递的过程。
会发现不管是
self、还是
super指向消息接受者是一样的,并且经过消息传递,最终处理消息的方法都是
NSObject中的
- (Class)class方法。
参考文章:
Objective-C Runtime深入理解Objective-C的Runtime机制
What exactly is super in Objective-C?
相关文章推荐
- 怎样使java程序减少内存占用(转载)
- 用3公升和5公升没有刻度的水杯量出4公升
- 【Code】Js-mind插件中会使用到的一个递归拼装数据格式的函数
- iOS开发 - 广播(跑马灯)的实现
- 嵌入式Linux开发第一弹 之 网络配置
- NSPredicate
- jQuery中自定义简单动画的实现
- Bzoj2599:[IOI2011]Race:树的点分治
- EmguCV的配置与使用
- PyCharm设置---更改主题、字体&显示行号
- [mongoDB]常用查询语句
- 二.有关磁盘空间的命令
- 超全!整理常用的iOS第三方资源
- .bash和.zsh的切换
- Android 避免APP启动闪黑屏(Theme和Style)
- 有故事的歌
- AutoInvoice in Oracle Apps R12
- java基础--正则表达式:Pattern类与Matcher类详解
- Kerberos 四幕话剧
- 第三方登陆,QQ互联