Objective-C中super和self的相關(guān)理解

一腹缩、說明

super:只是一個(gè)編譯器指示符屿聋,并不是指針或者對(duì)象,它只是標(biāo)識(shí)當(dāng)前對(duì)象去調(diào)用父類的方法
self: 實(shí)例方法里的self藏鹊,是對(duì)象的首地址 润讥,類方法里的 self 是 Class.

二、相關(guān)用法和區(qū)別
  1. [super class]
  2. [self class]
  3. [self superclass]
  4. [super superclass]
  5. self = [super init]
首先我們創(chuàng)建兩個(gè)類ClassA 盘寡、 ClassB ,讓ClassB繼承ClassA
@interface ClassA : NSObject
- (void)classAMethod;
@end

#import "ClassA.h"
@implementation ClassA
- (void)classAMethod{
    NSLog(@"調(diào)用了ClassA中的方法");
}
@end

#import "ClassA.h"
@interface ClassB :ClassA
- (void)classBMethod;
- (void)test;
@end


#import "ClassB.h"
@implementation ClassB
- (instancetype)init {
    self = [super init];
    if (self){

    }
    return self;
}
- (void)classBMethod {
    NSLog(@"[super class] == %@",[super class]);
    NSLog(@"[self class] == %@",[self class]);
    NSLog(@"[self superclass] == %@",[self superclass]);
    NSLog(@"[super superclass] == %@",[super superclass]);
}
- (void)classAMethod {
    NSLog(@"調(diào)用了ClassB中的方法");
}
- (void)test{
    [self classAMethod];
    [super classAMethod];
}
@end

我們?cè)? ViewController 中初始化 ClassB的實(shí)例 并調(diào)用 classBMethod 方法楚殿,得到下面的結(jié)果

 - (void)viewDidLoad {
    [super viewDidLoad];
    ClassB *instanceB = [[ClassB alloc] init];
    [instanceB classBMethod];
 }

2018-07-04 14:23:20.072983+0800 OCCodeDemo[73161:3730280] [super class] == ClassB
2018-07-04 14:23:20.073119+0800 OCCodeDemo[73161:3730280] [self class] == ClassB
2018-07-04 14:23:20.073237+0800 OCCodeDemo[73161:3730280] [self superclass] == ClassA
2018-07-04 14:23:20.073358+0800 OCCodeDemo[73161:3730280] [super superclass] == ClassA

我們可以看到 [super class] 和 [self class] 得到的結(jié)果是一樣的,都指向了當(dāng)前類ClassB竿痰,[self superclass] 和 [super superclass]都指向了父類ClassA脆粥,我們把 ClassB.m 文件編譯成 運(yùn)行時(shí)的代碼看一下,下面是classBMethod 方法運(yùn)行時(shí)代碼

static void _I_ClassB_classBMethod(ClassB * self, SEL _cmd) {
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_0,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("class")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_1,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_2,((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass")));
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_ps_vpyt2wb51qqcqlxlfqlntnmw0000gn_T_ClassB_942b53_mi_3,((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("superclass")));
} 

可以看到消息的接收者都是 self 影涉,也就是對(duì)象 instanceB (class 與 superclass 都是 NSObject 類中的內(nèi)部函數(shù))
這里的 sel_registerName 官方給出的定義是:Registers a method with the Objective-C runtime system, maps the method name to a selector, and returns the selector value
也就是說把方法注冊(cè)到運(yùn)行時(shí)系統(tǒng)中变隔,并把方法名字和selector 做映射,并返回 selector 的 值

接下來我們調(diào)用 test 方法蟹倾,得到了下面的結(jié)果
2018-07-04 15:07:49.387521+0800 OCCodeDemo[74261:3766110] 調(diào)用了ClassB中的方法
2018-07-04 15:07:49.387635+0800 OCCodeDemo[74261:3766110] 調(diào)用了ClassA中的方法
如果我們 把 classB中的 classAMethod 方法去掉匣缘,在次調(diào)用test 方法 ,會(huì)得到如下結(jié)果
2018-07-04 15:21:52.620538+0800 OCCodeDemo[74537:3777302] 調(diào)用了ClassA中的方法
2018-07-04 15:21:52.620654+0800 OCCodeDemo[74537:3777302] 調(diào)用了ClassA中的方法

出現(xiàn)這樣的結(jié)果主要原因和ObjectIve-C中runtime消息機(jī)制有關(guān)鲜棠,[self classAMethod]會(huì)被編譯器轉(zhuǎn)化為objc_msgSend(self,@selector(classAMethod)) , [super classAMethod]會(huì)被編譯器轉(zhuǎn)化為 objc_msgSendSuper(self, classAMethod) , self 是先查找本類的IMP肌厨,找到對(duì)應(yīng)的函數(shù)就進(jìn)行執(zhí)行,如果沒有找到就會(huì)到父類/超類中去查找 豁陆,而 super 是先從父類進(jìn)行查找柑爸,找到對(duì)應(yīng)的函數(shù)進(jìn)行執(zhí)行,如果沒有找到則繼續(xù)向父/超類查找盒音,但是接受消息的對(duì)象都是self 表鳍,至于為什么是self何址,我們看一下運(yùn)行時(shí) 代碼 ,可以看到接收消息的對(duì)象都是 self

static void _I_ClassB_test(ClassB * self, SEL _cmd) {

    ((void (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("classAMethod"));
    ((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("classAMethod"));
}   
以上的例子进胯,很好的說明了Super作為編譯標(biāo)識(shí)符,標(biāo)識(shí)當(dāng)前對(duì)象去調(diào)用父類的方法原押,但是接受消息的還是當(dāng)前對(duì)象
接下來我們探討下 self = [super init]

對(duì)于[super init]大家都非常熟悉了胁镐,但是[super init] 之后為什么會(huì)把值賦給self ,我們看下 NSObject.m 中的 init 方法實(shí)現(xiàn)

- (id)init {
    return _objc_rootInit(self);
}

id
_objc_rootInit(id obj)
{
    // In practice, it will be hard to rely on this function.
    // Many classes do not properly chain -init calls.
    return obj;
}

轉(zhuǎn)化成 運(yùn)行時(shí)代碼如下:

static instancetype _I_ClassB_init(ClassB * self, SEL _cmd) {
    self = ((ClassB *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ClassB"))}, sel_registerName("init"));
    if (self){

    }
    return self;
}

從運(yùn)行時(shí)的代碼可以看出诸衔,[super init] 最終返回的是一個(gè) ClassB 的實(shí)例對(duì)象盯漂,并賦值給 self

三、總結(jié)

本篇文章只是介紹了關(guān)鍵字符 super的定義和作用以及在系統(tǒng)運(yùn)行時(shí)和self的關(guān)系笨农,并未對(duì)self的做更詳細(xì)的探討就缆,如有不足之處歡迎指正,共同學(xué)習(xí)進(jìn)步

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末谒亦,一起剝皮案震驚了整個(gè)濱河市竭宰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌份招,老刑警劉巖切揭,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異锁摔,居然都是意外死亡廓旬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門谐腰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孕豹,“玉大人,你說我怎么就攤上這事十气±常” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵砸西,是天一觀的道長(zhǎng)椅野。 經(jīng)常有香客問我,道長(zhǎng)籍胯,這世上最難降的妖魔是什么竟闪? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮杖狼,結(jié)果婚禮上炼蛤,老公的妹妹穿的比我還像新娘。我一直安慰自己蝶涩,他們只是感情好理朋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布絮识。 她就那樣靜靜地躺著,像睡著了一般嗽上。 火紅的嫁衣襯著肌膚如雪次舌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天兽愤,我揣著相機(jī)與錄音彼念,去河邊找鬼。 笑死浅萧,一個(gè)胖子當(dāng)著我的面吹牛逐沙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洼畅,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼吩案,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了帝簇?” 一聲冷哼從身側(cè)響起徘郭,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎丧肴,沒想到半個(gè)月后崎岂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闪湾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年冲甘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片途样。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡江醇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出何暇,到底是詐尸還是另有隱情陶夜,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布裆站,位于F島的核電站条辟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏宏胯。R本人自食惡果不足惜羽嫡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肩袍。 院中可真熱鬧杭棵,春花似錦、人聲如沸氛赐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至滓侍,卻和暖如春蒋川,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撩笆。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工捺球, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浇衬。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像餐济,于是被迫代替她去往敵國(guó)和親耘擂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容