Objective - C 對象的本質(zhì)(三)對象的分類

(一)對象的分類

OC中的對象,主要有3種:instance對象(實例對象)class對象(類對象)meta-class對象(元類對象),我們在前兩章講的是instance對象

(1)instance對象
  1. instance對象就是通過類alloc出來的對象,同一個類多次alloc生成不同的實例對象,分別處在不同的內(nèi)存地址
  2. instance對象中包含信息:isa指針、其他成員變量
(2)class對象
  1. class對象是唯一的,一個類只有一個class對象
  2. class對象在內(nèi)存中存儲的信息主要包括:
  • isa指針
  • superclass指針
  • 類的屬性信息(@property)、類的對象方法信息(instance method)
  • 類的協(xié)議信息(protocol)、類的成員變量信息(ivar)
  • ......等等

如何得到一個類的類對象呢?

  ZQPerson *personInstance = [[ZQPerson alloc]init];//ZQPerson實例對象
  personInstance.no = 432423;

  //下面的三個都是ZQPerson的class對象(類對象)
  Class personClass1 = [personInstance class];
  Class personClass2 = [ZQPerson class];//不管調(diào)用多少次class方法都只能獲取類對象
  Class personClass3 = object_getClass(personInstance);//Runtime API

NSLog(@"\nclass對象:\n %p \n %p \n %p",personClass1,personClass2,personClass3);//
  /*
    instance對象:
      0x10060ffb0
    class對象:地址都相同
      0x1000024c0
      0x1000024c0
      0x1000024c0
  */
(3)meta-class對象
  1. 每個類在內(nèi)存中有且只有一個meta-class對象
  2. meta-class對象和class對象的內(nèi)存結(jié)構(gòu)是一樣的,但是用途不一樣,在內(nèi)存中存儲的信息主要包括:
  • isa指針
  • superclass指針
  • 類的類方法信息(class method)
  Class personMetaClass = object_getClass(personClass1);
  NSLog(@"\nmeta-class對象:\n %p",personMetaClass);
  /*
    meta-class對象:
      0x1000024b8
  */

內(nèi)存結(jié)構(gòu)一樣,是指class對象和meta-class對象結(jié)構(gòu)一樣,只不過存儲的信息不同,用途不同,如:class對象也有類方法信息,只是里面為空,meta-class也是對應(yīng)的;

//判斷某個對象是否是元類對象
NSLog(@"%d",class_isMetaClass(personMetaClass));//1
(4) object_getClass方法

在上面我們發(fā)現(xiàn)多次調(diào)用了object_getClass方法,傳入的對象也不同,得到不同的結(jié)果,是為什么呢?

我們在runtime源碼objc-class.mm中可以找到:

Class object_getClass(id obj)
{
    //1.如果傳入的是istance對象,返回class對象
    //2.如果傳入的是class對象,返回的是meta-class對象
    //3.如果傳入的是meta-class,返回NSObject(基類)的meta-class對象
    if (obj) return obj->getIsa();
    else return Nil;
}
(5) objc_getClass方法

我們再查看一下objc_getClass方法:

Class objc_getClass(const char *aClassName)
{
    if (!aClassName) return Nil;

    // NO unconnected, YES class handler
    return look_up_class(aClassName, NO, YES);
}


Class 
look_up_class(const char *name, 
              bool includeUnconnected __attribute__((unused)), 
              bool includeClassHandler __attribute__((unused)))
{
    if (!name) return nil;

    Class result;
    bool unrealized;
    {
        runtimeLock.lock();
        result = getClassExceptSomeSwift(name);//調(diào)用這個方法,繼續(xù)跟進
        unrealized = result  &&  !result->isRealized();
        if (unrealized) {
            result = realizeClassMaybeSwiftAndUnlock(result, runtimeLock);
            // runtimeLock is now unlocked
        } else {
            runtimeLock.unlock();
        }
    }

    ...//省略代碼
    return result;
}


static Class getClassExceptSomeSwift(const char *name)
{
    runtimeLock.assertLocked();

    // Try name as-is
    Class result = getClass_impl(name);//獲取類對象
    if (result) return result;

    // Try Swift-mangled equivalent of the given name.
    if (char *swName = copySwiftV1MangledName(name)) {
        result = getClass_impl(swName);
        free(swName);
        return result;
    }

    return nil;
}

我們可以看出,objc_getClass方法傳入一個類名,返回的是class對象,無法獲取meta-class對象

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

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