OC對象的本質(zhì)(中)—— OC對象的種類

OC對象的本質(zhì)(上):OC對象的底層實現(xiàn)原理
OC對象的本質(zhì)(中):OC對象的種類
OC對象的本質(zhì)(下):詳解isa&superclass指針

Objective-C中的對象,簡稱OC對象,主要分3類

  • instance對象(實例對象)
  • class對象(類對象)
  • meta-class對象(元類對象)

instance 實例對象

instance對象就是通過alloc方法創(chuàng)建出來的對象,每次調(diào)用alloc方法都會生成新的instance對象

NSObjcet *object1 = [[NSObject alloc] init];
NSObjcet *object2 = [[NSObject alloc] init];

上面的object1 object2都是NSObject的instance對象(實例對象),因為他們都有自己的獨有內(nèi)存,所以是兩個不同的對象

instance對象在內(nèi)存中存放的信息包括

  • isa指針(因為基本上我們常用的類以及自定義類都繼承自NSObject,所以我們這里討論的instance里面都包含isa指針)
  • 其他成員變量

class 類對象

class對象的作用是用來描述一個instance對象,它內(nèi)部存放一個類的屬性信息(@property)、對象方法信息(instance method)、協(xié)議信息(protocol)、成員變量信息(ivar),另外class對象里面還有兩個指針,isa指針 和 superclass指針。

可以通過一下方法,獲取一個類的類對象

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        
        NSObject *obj1 = [[NSObject alloc] init];
        NSObject *obj2 = [[NSObject alloc] init];
        
        Class objClass1 = [NSObject class];
        Class objClass2 = [obj1 class];
        Class objClass3 = [obj2 class];
        Class objClass4 = object_getClass(obj1);
        Class objClass5 = object_getClass(obj2);
        //一個類在內(nèi)存中只存一份
        NSLog(@"\nobjClass1:%p\nobjClass2:%p\nobjClass3:%p\nobjClass4:%p\nobjClass5:%p",
              objClass1,
              objClass2,
              objClass3,
              objClass4,
              objClass5);
        
        }
    return 0;
}

如上圖打印結(jié)果,可以看出,一個類的類對象是唯一的,在內(nèi)存中只存一份,這也很好理解,因為類對象中的信息只需要一份就夠了。

meta-class 元類對象

meta-class對象的作用是用來描述一個class對象。跟class一樣,元類對象在內(nèi)存中也是只有一份的。它內(nèi)部存儲了 isa指針 + superclass指針 + 類方法信息(+方法)

下面是元類對象一些相關(guān)的api:

  • object_getClass(<class對象>);獲取元類對象,參數(shù)為一個類對象
  • class_isMetaClass(<class對象/meta-class對象>);判斷是否是元類對象

因為classmeta-class對象都可以通過object_getClass獲得,因此他們的類型都是一樣的,都是typedef struct objc_class *Class這個Class類,可以理解,它們各自利用Class的一些成員變量來實現(xiàn)自己的功能。

幾個常用方法的區(qū)別
(a)Class objc_getClass(const char *aClassName)
  • 入?yún)⑹且粋€字符串,也就是類名
  • 返回值是對應(yīng)的class對象
  • 因為我們通過字符串,只能定義類的名字,所以這個方法只能返回class對象
(b)Class object_getClass(id obj)
  • 入?yún)?code>obj可以是instance對象class對象或者meta-class對象
  • 返回值
    • 傳入instance對象,返回對應(yīng)的class對象
    • 傳入class對象,返回對應(yīng)的meta-class對象
    • 傳入meta-class對象,返回NSObject(基類)meta-class對象
/***********************************************************************
* object_getClass.
* Locking: None. If you add locking, tell gdb (rdar://7516456).
**********************************************************************/
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();
    else return Nil;
}

根據(jù)上面的object_getClass的源碼實現(xiàn),我們看到,這個方法返回的是isa指針。

我用僅有的一點美術(shù)功底,手繪描述了一下各種isa間的關(guān)系,所以根據(jù)instanceisa可以得到它的class對象,根據(jù)classisa指針,可以得到它的meta-class對象,至于meta-class的isa`指針問題,我們留到下一章仔細(xì)論述。

(c)- (Class)class & + (Class)class

一個類的實例方法和類方法里面都有這個方法。我們用代碼來測試一下

#import <Foundation/Foundation.h>
#import <objc/runtime.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        
        NSObject *obj1 = [[NSObject alloc] init];
        
        Class objClass1 = [NSObject class];
        Class objClass2 = [obj1 class];
        Class objClass3 = [objClass1 class];
        Class objClass4 = [objClass2 class];
        //一個類在內(nèi)存中只存一份
        NSLog(@"\nobjClass1:%p\nobjClass2:%p\nobjClass3:%p\nobjClass4:%p",
              objClass1,
              objClass2,
              objClass3,
              objClass4);
        
        }
    return 0;
}

輸出結(jié)果如下


根據(jù)結(jié)果,我們可以總結(jié)出,一個class對象調(diào)用(Class)class方法,返回的不是它的meta-class對象,而是它自身。總之,不論- (Class)class 還是 + (Class)class,都只能返回一個類的`class對象



OC對象的本質(zhì)(上):OC對象的底層實現(xiàn)
OC對象的本質(zhì)(中):OC對象的分類
OC對象的本質(zhì)(下):詳解isa&superclass指針

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。