Self 和Super 解釋

1、self 和 super的官方解釋

self
Whenever you’re writing a method implementation, you have access to an important hidden value, self. Conceptually, self is a way to refer to “the object that’s received this message.” It’s apointer, just like the greeting value above, and can be used to call a method on the current receiving object.

super
super is a flag that tells the compiler to search for the method implementation in a very different place. It begins in the superclass of the class that defines the method where super appears.

結(jié)論:

self : 是一個(gè)隱私參數(shù),熟悉C的都知道猪狈,他和 _cmd構(gòu)成方法的參數(shù),self是動(dòng)態(tài)的;執(zhí)行時(shí)調(diào)用RT的objc_msgSend();

super : 是個(gè)編譯器的指令符號,只是告訴編譯器在執(zhí)行的時(shí)候,去調(diào)誰的方法.super是編譯的桥状;執(zhí)行時(shí)調(diào)用RT的objc_msgSendSuper();

self 調(diào)用的是本類的方法茂缚,super調(diào)用的是父類中的方法戏罢。

2、self 和 super的底層實(shí)現(xiàn)原理:

將下面的代碼clang后阱佛,我們來看一下這兩句代碼到底是怎樣轉(zhuǎn)化并執(zhí)行的:

- (void)test{
    [self class];
    [super class];
}

編譯后的代碼:

static void _I_Man_test(Man * self, SEL _cmd) {
    ((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"));//[self class]調(diào)用
    ((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Man"))}, sel_registerName("class"));//[super class]調(diào)用
}

經(jīng)過clang后帖汞,編譯為上面的代碼,簡化一下可以看到:[self class]實(shí)際上轉(zhuǎn)換成為objc_msgSend()來發(fā)送消息凑术。 [super class]實(shí)際上轉(zhuǎn)換為objc_msgSendSuper()來發(fā)送消息翩蘸。

分別看下objc_msgSend()和objc_msgSendSuper()的定義。

1)objc_msgSend()函數(shù)聲明如下:

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

theReceiver:消息接受者淮逊,theSelector:要調(diào)用的方法催首,后面為可變參數(shù)。其中self就是這里的theReceiver參數(shù)泄鹏。

2)objc_msgSendSuper()函數(shù)聲明如下:

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

第一個(gè)參數(shù)是是一個(gè)objc_super 結(jié)構(gòu)體郎任,不再是一個(gè)id類型的對象,后面的參數(shù)跟objc_msgSend相同备籽,分別是selector和可選參數(shù)舶治。

3) 我們再來看一下struct objc_super定義:

/// Specifies the superclass of an instance. 
struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;

    /// Specifies the particular superclass of the instance to message. 
#if !defined(__cplusplus)  &&  !__OBJC2__ //這里采用宏判斷,現(xiàn)在是OBJC2.0,所以不會(huì)走這個(gè)if车猬。
    /* For compatibility with old objc-runtime.h header */
    __unsafe_unretained _Nonnull Class class;
#else
    __unsafe_unretained _Nonnull Class super_class;
#endif
};

我們可以看到結(jié)構(gòu)體主要是由reviceiver和super_class構(gòu)成的霉猛。而receiver就是一個(gè)類的實(shí)例對象(也就是self),super_class則是指向父類珠闰。即:首先從super->super_class指向的父類的方法中查找對應(yīng)的selector惜浅,找到后再使用 super->receiver 調(diào)用對應(yīng)的selector。

了解了底層實(shí)現(xiàn)后伏嗜,我們也就清楚為什么 [self class][super class]返回值是相同的坛悉。
再來看一個(gè)例子:

@implementation Person

- (void)personBaseMethod {
    NSLog(@"%@",[self class]);
}

@end


@implementation Student

- (void)personBaseMethod {
    NSLog(@"%@",[self class]);
    NSLog(@"========");
    [super personBaseMethod];
}

//調(diào)用 Student中的personBaseMethod 打印結(jié)果如下:
Student
========
Student

self指向的是當(dāng)前Student的實(shí)例對象,而super則是:先去父類的方法列表中找到personBaseMethod伐厌,然后給self(也就是Student的實(shí)例對象)發(fā)消息。由self對象來執(zhí)行父類personBaseMethod這個(gè)方法體中的[self class]裸影。 所以最終還是由self來執(zhí)行sel_registerName("class") 這個(gè)selector挣轨。

關(guān)于objc_msgSend函數(shù)的實(shí)現(xiàn)我們是看不到的,它的實(shí)現(xiàn)是以匯編語言完成的空民。這里有一篇博客刃唐,作者根據(jù)機(jī)器碼反推出了實(shí)現(xiàn)。

2界轩、為什么要有 self = [super init];

init方法在初始化失敗后會(huì)返回nil画饥,OC中關(guān)于 init 的約定有一個(gè)重要部分:可以通過返回 nil 來告訴調(diào)用者,初始化失敗了浊猾;(初始化可能會(huì)因?yàn)楦鞣N原因失敗抖甘,比如一個(gè)輸入的格式錯(cuò)誤了,或者另一個(gè)需要的對象初始化失敗了葫慎。)
這樣我們就能理解為什么總是需要調(diào)用 self = [super init]衔彻。
原因就是:1、如果父類說初始化自己的時(shí)候失敗了偷办,那么必須假定當(dāng)前的self實(shí)例正處于一個(gè)不穩(wěn)定的狀態(tài)艰额,因此在你的實(shí)現(xiàn)里不要繼續(xù)你自己的初始化并且也返回 nil。如果不這樣做椒涯,你可能會(huì)操作一個(gè)不可用的對象柄沮,它的行為是不可預(yù)測的,最終可能會(huì)導(dǎo)致你的程序崩潰废岂。
2祖搓、alloc后返回的是一個(gè)有效但初始化的對象,init負(fù)責(zé)初始化對象湖苞,拯欧,使對象處于可用狀態(tài)。所以沿著繼承鏈往上調(diào)用init犯法财骨,使得對象的各級父類都能夠完成初始化操作镐作,并為其實(shí)例變量賦予合理的值。

3隆箩、關(guān)于OC的alloc 和 init(摘自:OC禪與藝術(shù) )

我們常常寫 [[NSObject alloc] init] 這樣的代碼滑肉,從而淡化了 alloc 和 init 的區(qū)別。Objective-C 的這個(gè)特性叫做 兩步創(chuàng)建摘仅。

這意味著申請分配內(nèi)存和初始化被分離成兩步,alloc 和 init问畅。

 1娃属、 alloc 負(fù)責(zé)創(chuàng)建對象六荒,這個(gè)過程包括分配足夠的內(nèi)存來保存對象,寫入 isa 指針矾端,初始化引用計(jì)數(shù)掏击,以及重置所有實(shí)例變量。
 2秩铆、init 負(fù)責(zé)初始化對象砚亭,這意味著使對象處于可用狀態(tài)。這通常意味著為對象的實(shí)例變量賦予合理有用的值殴玛。

alloc 方法將返回一個(gè)有效的未初始化的對象實(shí)例捅膘。每一個(gè)對這個(gè)實(shí)例發(fā)送的消息會(huì)被轉(zhuǎn)換成一次 objc_msgSend() 函數(shù)的調(diào)用,形參 self 的實(shí)參是 alloc 返回的指針滚粟;這樣 self 在所有方法的作用域內(nèi)都能夠被訪問寻仗。

按照慣例,為了完成兩步創(chuàng)建凡壤,新創(chuàng)建的實(shí)例第一個(gè)被調(diào)用的方法將是 init 方法署尤。注意,NSObject 在實(shí)現(xiàn) init 時(shí)亚侠,只是簡單的返回了 self曹体。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市硝烂,隨后出現(xiàn)的幾起案子箕别,更是在濱河造成了極大的恐慌,老刑警劉巖钢坦,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件究孕,死亡現(xiàn)場離奇詭異,居然都是意外死亡爹凹,警方通過查閱死者的電腦和手機(jī)厨诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來禾酱,“玉大人微酬,你說我怎么就攤上這事〔眨” “怎么了颗管?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滓走。 經(jīng)常有香客問我垦江,道長,這世上最難降的妖魔是什么搅方? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任比吭,我火速辦了婚禮绽族,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衩藤。我一直安慰自己吧慢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布赏表。 她就那樣靜靜地躺著检诗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瓢剿。 梳的紋絲不亂的頭發(fā)上逢慌,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音跋选,去河邊找鬼涕癣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛前标,可吹牛的內(nèi)容都是我干的坠韩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼炼列,長吁一口氣:“原來是場噩夢啊……” “哼只搁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起俭尖,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤氢惋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后稽犁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焰望,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年已亥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熊赖。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡虑椎,死狀恐怖震鹉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捆姜,我是刑警寧澤传趾,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站泥技,受9級特大地震影響浆兰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一镊讼、第九天 我趴在偏房一處隱蔽的房頂上張望宽涌。 院中可真熱鬧,春花似錦蝶棋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至段直,卻和暖如春吃溅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鸯檬。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工决侈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喧务。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓赖歌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親功茴。 傳聞我的和親對象是個(gè)殘疾皇子庐冯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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

  • 今天是房東蔣老頭這個(gè)月第四次敲響306的房門,房租已經(jīng)拖欠兩個(gè)月了坎穿,蔣老頭下定決心今天要敲開306的門展父,告訴房客自...
    九丑_閱讀 891評論 7 16
  • 項(xiàng)目中的更新下載,圖片拍照玲昧,如果是7.0以下栖茉,沒有發(fā)現(xiàn)任何異常,但是到了7.0以上孵延,你會(huì)發(fā)現(xiàn)吕漂,你大爺已經(jīng)不是以前的...
    大川的川閱讀 2,303評論 0 0
  • 2019.2.25 今天多云,星期一 昨天晚上坐火車10+個(gè)小時(shí)隙袁,今天早晨回到家痰娱,整理一下衛(wèi)生和帶...
    志枚閱讀 68評論 0 2
  • 今天是年初二。除夕那天菩收,從下午看到哈迪的文章之后梨睁,我決定給朋友們一個(gè)個(gè)地發(fā)祝福語。 其實(shí)中午開始已經(jīng)陸續(xù)收到一些祝...
    saiyonana閱讀 171評論 0 0