[CH2-Q2]Objective-C對象中的isa、superclass指針

上一節Objective-C的對象——實例對象、類對象、元類對象我們總結出:
OC中的對象分成三類,分別包括: instance(實例對象)、class(類對象)、meta-class(元類對象)。如下圖,并且我們發現①實例對象都會存儲類的成員變量,其中有一個特殊的成員變量就是isa。②類對象存儲 isa、superclass、成員變量相關的信息、協議信息、屬性、對象方法等信息。③元類對象存儲isa、superclass、類方法。

通過上面對比三種OC對象,我們可以發現有兩個很的特殊的指針:isa指針和superclass指針。其中instance、class、meta-class三種對象都有isa指針,而class、meta-class兩種對象都有superclass指針。那今天我們就聊一下isa指針和superclass指針。

15464387558687.jpg
15464389258320.jpg

三種OC對象是如何聯系的?

在聊isa和superclass之前,我們先討論一個問題:一個自定義Person類的實例對象p,要想調用對象方法(- personInstanceMethod)和類方法(+ personClassMethod),它的底層是如何實現的?

@interface Person : NSObject

- (void)personInstanceMethod;
+ (void)personClassMethod;

@end

@implementation Person

- (void)personInstanceMethod {
    
}

+ (void)personClassMethod {
    
}

@end
    // mian方法中
    Person *p = [[Person alloc] init];
    [p personInstanceMethod];
    [Person personClassMethod];;

上面的代碼我們聲明了一個Person類,并且有一個對象方法和一個類方法,在程序的main方法中alloc、init了一個指針名為p的實例對象,分別用p調用對象方法personInstanceMethod,用Person調用類方法personClassMethod。我們知道OC中是通過消息發送機制來調用方法的,我們可以把[p personInstanceMethod]這句代碼翻譯成底層調用代碼為objc_msgSend(p, @selector(personInstanceMethod));,我們發現,OC底層的代碼是向p這個實例對象發送消息的,但是我們知道:對象方法的信息其實是在Person類對象里面存儲的,因此我們可以猜想實例對象類對象擁有某種聯系。同理我們使用Person類對象調用類方法personClassMethod,objc_msgSend方法是向類對象Person發送消息的,但我們知道類對象并沒有存儲類方法,而元類對象有存儲類方法,因此類對象和元類對象也是有一定的聯系。

我們也可以通過xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 命令讓其轉化成C、C++代碼觀察

15464396381746.jpg

OC對象的isa指向哪里?

通過對上面問題的討論,我們可以猜想instance、class、meta-class三種對象是有一定聯系的。其實他們是通過isa指針去聯系起來的。

實例對象的isa指向類對象,類對象的isa指向元類對象。

①實例對象的isa指向類對象,當調用對象方法時,通過instance的isa找到class,最后找到對象方法的實現進行調用。

(例如:上面的例子,實例對象p調用personInstanceMethod對象方法,其實是通過實例對象的isa指針先找到類對象Person,再從類對象的內從中找到personInstanceMethod的方法實現進行調用)

②類對象的isa指向元類對象,當調用類對象方法時,通過類對象的isa找到元類對象,最后找到類方法的實現進行調用。

(例如:上面的例子,類對象Person調用personClassMethod類方法,其實是通過類對象的isa指針先找到元類對象meta-person,再從元類對象的內從中找到personInstanceMethod的方法實現進行調用)

15465293909682.jpg

擁有繼承關系的對象是如何聯系的?

isa指針只是解決了一個類中的聯系,但是如果擁有繼承關系的類之間又是通過什么聯系的呢?在討論這個問題之前我們再來做一個場景:

在(三種OC對象是如何聯系的?)的代碼的基礎上我們再添加一個繼承于Person這個類的Student類,并聲明和實現了類方法 studentClassMethod 和 對象方法 studentInstanceMethod

@interface Person : NSObject

- (void)personInstanceMethod;
+ (void)personClassMethod;

@end

@implementation Person

- (void)personInstanceMethod {
    
}

+ (void)personClassMethod {
    
}

@end

@interface Student : Person

- (void)studentInstanceMethod;
+ (void)studentClassMethod;

@end

@implementation Student

- (void)studentInstanceMethod {
    
}

+ (void)studentClassMethod {
    
}

@end
//main 方法中
    Student *stu = [[Student alloc] init];
    [stu studentInstanceMethod]; //①
    [stu personInstanceMethod];  //②
    
    [Student studentClassMethod];  //③
    [Student personClassMethod];  //④

我們先看①:stu實例對象調用實例方法studentInstanceMethod,通過我們剛才的討論,stu實例對象先通過它自己的isa指針找到Student類對象,再找到實例方法的實現從而進行調用。

接著我們再看③:Student類對象調用類方法studentClassMethod,也是通過我們剛才的討論,Student類對象先通過它自己的isa指針找到meta-class元類對象,再找到類方法的實現從而進行調用。

但是我們再看看②和④就會發現,Student類對象和元類對象都沒有personInstanceMethodpersonClassMethod的方法,那么又是怎么去實現的呢?

superclass指針指向哪里?

在上面的(擁有繼承關系的對象是如何聯系的?),我們發現子類和父類之間需要有一定的聯系,才能讓子類去調用父類聲明的方法還有使用父類的成員屬性等。那又是通過什么去聯系的呢?其實它們之間就是通過superclass指針去聯系的。不過類對象的superclass指針和元類對象的superclass稍微有一些不同,我們先說一下類對象的superclass指針。

現在各個類的繼承關系如下: @interface Student : Person,@interface Person : NSObject, Student 類對象、 Person 類對象、NSObject 類對象 它們都各自存放著各自的 isa、superclass、成員變量相關的信息、協議信息、屬性、對象方法,這三個類對象的聯系其實很簡單,他們就是通過superclass指針聯系起來的。

Student類對象的superclass指針指向Person類對象,Person類對象的superclass指針指向NSObject類對象。

因此我們可以解答剛才的問題,stu實例對象是如何調用父類的實例方法:personInstanceMethod?

    Student *stu = [[Student alloc] init];
    [stu personInstanceMethod];

由于Student類繼承于Person類,上面的方法調用通過轉換成C、C++語言其實就是:objc_msgSend(stu, @selector(personInstanceMethod));,stu實例對象是不存儲方法信息的,因此通過isa指針先找到它的類對象Student,但Student類對象并沒有該方法,所以可以通過Student類對象的superclass指針找到Person類對象,從而找到personInstanceMethod的方法實現并調用。

15464415747011.jpg

我們說完類對象superclass指針,再說以元類對象superclass指針。我們還是使用上面的繼承關系:@interface Student : Person,@interface Person : NSObject

Student元類對象的superclass指針指向Person元類對象,Person元類對象的superclass指針指向NSObject元類對象。

     [Student personClassMethod];

上面的方法調用通過轉換成C、C++語言其實就是:objc_msgSend(Student, @selector(personClassMethod));,Student類對象的isa找到Student的元類對象,但Student元類對象的類方法列表并沒有personClassMethod,因此通過Student元類對象的superclass指針找到Person元類對象,從而找到哦personClassMethod的方法實現并進行調用。

15465315094204.jpg

通過上面討論類對象的superclass指針和元類對象的superclass指針我們可以得到的信息就是:

類對象的superclass指針指向它父類的類對象。
元類對象的superclass指針指向它父類的元類對象。

isa、superclass總結

  • instance的isa指向class

  • class的isa指向meta-class

  • meta-class的isa指向基類的meta-class

  • class的superclass指向父類的class,如果沒有父類,superclass指針為nil

  • meta-class的superclass指向父類的meta-class;基類的meta-class的superclass指向基類的class

  • instance調用對象方法的軌跡;isa找到class,方法不存在,就通過superclass找父類

  • class調用類方法的軌跡;isa找meta-class,方法不存在,就通過superclass找父類

15465326750562.jpg
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

  • iOS底層原理總結 - 探尋OC對象的本質 對小碼哥底層班視頻學習的總結與記錄。面試題部分,通過對面試題的分析探索...
    xx_cc閱讀 21,502評論 31 178
  • 前言:本文簡述OC對象、isa和SuperClass,如有錯誤請留言指正。 Q:OC中對象分類 A:總共為三類:實...
    夢蕊dream閱讀 4,135評論 6 16
  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,751評論 0 9
  • 一、Objective-C對象的分類 Objective-C中的對象,簡稱OC對象,主要可以分為3種 instan...
    紫荊秋雪_文閱讀 857評論 0 1
  • 于是周勤在秦裘家借住了一晚上,本來秦裘是怎么也不肯,就說要他往深山的老宅住去,那兒省心。但老宅陰氣重,早八百年前就...
    狗子家閱讀 308評論 2 3