在上一篇文章中,我們講了NSObject本質(zhì),其實(shí)上一篇文章講的是實(shí)例對(duì)象
Objective-C中的對(duì)象,簡(jiǎn)稱OC對(duì)象,主要可以分為3種:
instance對(duì)象(實(shí)例對(duì)象)
class對(duì)象(類對(duì)象)
meta-class對(duì)象(元類對(duì)象)
一. instance對(duì)象(實(shí)例對(duì)象)
instance對(duì)象就是通過(guò)類alloc出來(lái)的對(duì)象,每次調(diào)用alloc都會(huì)產(chǎn)生新的instance對(duì)象,分別占據(jù)著兩塊不同的內(nèi)存
instance對(duì)象在內(nèi)存中存儲(chǔ)的信息包括:isa指針和其他成員變量
比如有如下類:
@interface Person : NSObject
{
@public
int _age;
}
@end
Person *p1 = [[Person alloc] init];
p1->_age = 3;
Person *p2 = [[Person alloc] init];
p2->_age = 4;
那么p1和p2在內(nèi)存中的結(jié)構(gòu)為:
二. class對(duì)象(類對(duì)象)
每個(gè)類在內(nèi)存中有且只有一個(gè)class對(duì)象
如何獲取class對(duì)象:
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
//獲取類對(duì)象的三種方式 ,并且類對(duì)象是唯一的
Class objectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1);
Class objectClass4 = object_getClass(object2);
Class objectClass5 = [NSObject class];
//實(shí)例對(duì)象地址不一樣
NSLog(@"%p %p",
object1,
object2);
//0x100534680 0x100534490
//類對(duì)象地址一樣的,是唯一的
NSLog(@"%p %p %p %p %p",
objectClass1,
objectClass2,
objectClass3,
objectClass4,
objectClass5);
// 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140 0x7fff97e99140
上面代碼objectClass1~objectClass5都是NSObject的class對(duì)象(類對(duì)象),它們是同一個(gè)對(duì)象。
注意:
class方法返回的一直是class類對(duì)象,不管你調(diào)用多少次,也不會(huì)得到元類對(duì)象
Class objectMetaClass2 = [[[NSObject class] class] class]; //還是類對(duì)象
獲取class對(duì)象的三種方式
Class objectClass1 = [object1 class]; //對(duì)象的class方法
Class objectClass2 = [NSObject class]; //類的class方法
Class objectClass3 = object_getClass(object1); //傳入對(duì)象
class對(duì)象在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superclass指針
類的屬性信息(@property)、類的成員變量信息(ivar)
類的協(xié)議信息(protocol)、類的對(duì)象方法信息(instance method)
......
如下圖:
三. meta-class對(duì)象(元類對(duì)象)
每個(gè)類在內(nèi)存中有且只有一個(gè)meta-class對(duì)象
獲取meta-class對(duì)象,只有一種方法:
Class objectMetaClass = object_getClass([NSObject class]);//傳入一個(gè)class對(duì)象
objectMetaClass是NSObject的meta-class對(duì)象(元類對(duì)象)
注意:
- 將類對(duì)象當(dāng)做參數(shù)傳入object_getClass,獲得元類對(duì)象
- 類對(duì)象和元類對(duì)象都是Class類型的
meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的,但是用途不一樣,在內(nèi)存中存儲(chǔ)的信息主要包括:
isa指針
superclass指針
類的類方法信息(class method)
......
看下圖你就明不白了,為什么meta-class對(duì)象和class對(duì)象的內(nèi)存結(jié)構(gòu)是一樣的,但是存儲(chǔ)的信息不一樣,因?yàn)樗麄兊淖饔貌灰粯?/p>
補(bǔ)充:class_isMetaClass(objectMetaClass)可以判斷是不是元類對(duì)象
四. 查看object_getClass函數(shù)底層是如何實(shí)現(xiàn)的
1. object_getClass
在objc4中搜索函數(shù)名,找到了object_getClass的底層實(shí)現(xiàn)
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}
可以發(fā)現(xiàn),返回的是isa,所以:
如果傳進(jìn)來(lái)的是instance對(duì)象,返回class類對(duì)象
如果傳進(jìn)來(lái)的是class類對(duì)象,返回metra-class元類對(duì)象
如果傳進(jìn)來(lái)的是metra-class對(duì)象,返回NSObject(基類)的metra-class對(duì)象
2. objc_getClass
順便查看一下objc_getClass函數(shù)底層實(shí)現(xiàn),這個(gè)不太好分析,直接記結(jié)論:objc_getClass函數(shù)傳入一個(gè)字符串類名,返回一個(gè)類對(duì)象
Class objc_getClass(const char *aClassName)
{
//這個(gè)方法是
if (!aClassName) return Nil;
// NO unconnected, YES class handler
return look_up_class(aClassName, NO, YES);
}
3. - (Class)class、+ (Class)class
它們的底層實(shí)現(xiàn):
- (Class) {
return self->isa;
}
//如果是對(duì)象方法,返回isa就返回了當(dāng)前的類對(duì)象
+ (Class) {
return self;
}
//如果是類方法,返回自己就是類對(duì)象
綜上,這兩個(gè)class方法返回的就是類對(duì)象
Demo地址:OC對(duì)象的分類