您的位置:首页 > 移动开发 > Objective-C

Objective-C关键字self和super详解

2015-06-08 10:43 519 查看

背景

对于self和super这两个关键字,最初的理解是:想当然的以为与java及c++中的this和super用法一致。然而实际上并非完全如此,我们通过一个例子来说明OC中的self和super的实现原理。

例子

有Man和Person两个类:



Man是Person的子类,在Man类中实现一个方法来打印class方法的值(class方法用来表示方法接收者所在的类)。

最初猜测的打印结果:

Man
Person


实际的打印结果:



为什么是这样呢?

真相

self:类的隐藏参数,指向当前调用方法的类。对于静态方法,self指向类对象;对于实例方法,self指向实例对象。

super:“编译器指示符”,表示从父类中查找成员变量或方法。

那么,[self class]与[super class]这两种调用方式为什么会返回相同的结果呢?这就要谈到objective – C的消息机制了。

在OC中,对象调用方法被称为给对象发送消息,如[self class]表示给self指向的对象发送一个方法名为class的消息。

当调用方法的时候,编译器会将其转化成下面4个方法之一:

objc_msgSend
objc_msgSend_stret
objc_msgSendSuper
objc_msgSendSuper_stret


通过[self methodName]调用时,会转化为 [b]objc_msgSendobjc_msgSend_stret;[/b]

通过[super methodName]调用时,会转化为 [b]objc_msgSendSuperobjc_msgSendSuper_stret。[/b]

注:_stret系列表示方法的返回值类型为一个结构体,如CGRect。

objc_msgSend

函数定义

* id objc_msgSend(id theReceiver ,SEL theSelector, ...)


参数说明

以[self class]为例:

第一个参数是消息接收者,也就是Man类的实例;

第二个参数是方法的selector,也就是@selector(class);

省略号表示方法的可变参数。

函数执行流程

从self的类的方法列表中找class这个方法,找到执行3,否则执行2。

去其父类的方法列表中找class这个方法,找到执行3,否则执行2。

把selector传递给接收者。

objc_msgSendSuper

函数定义

id objc_msgSendSuper(struct objc_super *super, SEL op, ...)


参数说明

以[super class]为例:

第一个参数是个结构体

第二个参数是方法的selector

struct objc_super {
id receiver; //消息接收者
Class superClass; //该类的父类
};


函数的执行流程

构建objc_super的结构体,这个结构体的第一个变量receiver为Man,与self相同;第二个成员变量superClass是Person,是self对应类的超类。

从superClass代表的类的方法列表中寻找class方法,找到执行3,否则继续向上去父类中找class方法。

把selector传递给接收者。

从上面的分析中看出,原来当我们调用[self class]、[super class]时,它们的消息接收者都是一样的,即Men这个类的一个实例,只不过是寻找class方法时有所区别。

小结

OC中的self和super,与c++和java中this和super的用法是有一些异同的.

相同点

在类的实例方法中,self表示指向实例对象的指针,可以用来调用该类的成员变量和实例方法;super可以用来调用父类的成员变量和实例方法。

不同点

在类的静态方法中,self和super也可以使用,这时self指向该类对象,可以用来调用该类的静态方法;super可以用来调用父类的静态方法。

super只是一个”编译器指示符”,表示去父类的方法列表中寻找相应方法。消息接收者始终是调用[super xxx]的那个类对象或类实例对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  oc 关键字