備注:文章主要學(xué)習(xí)自飄飄白云的博客
Object & Class & Meta Class
objc中 class 與 object 的定義:
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
Class 是一個(gè) objc_class 結(jié)構(gòu)類(lèi)型的指針;而 id(任意對(duì)象) 是一個(gè) objc_object 結(jié)構(gòu)類(lèi)型的指針揍异,其第一個(gè)成員是一個(gè) objc_class 結(jié)構(gòu)類(lèi)型的指針仁堪。注意這里有一關(guān)鍵的引申解讀:內(nèi)存布局以一個(gè) objc_class 指針為開(kāi)始的所有東東都可以當(dāng)做一個(gè) object 來(lái)對(duì)待螃宙!
那 objc_class 又是怎樣一個(gè)結(jié)構(gòu)體呢?且看:
struct objc_class{
struct objc_class* isa;
struct objc_class* super_class;
const char* name;
long version;
long info;
long instance_size;
struct objc_ivar_list* ivars;
struct objc_method_list** methodLists;
struct objc_cache* cache;
struct objc_protocol_list* protocols;
};
類(lèi)之間的關(guān)系
規(guī)則一:類(lèi)的實(shí)例對(duì)象的 isa 指向該類(lèi)坞靶;該類(lèi)的 isa 指向該類(lèi)的 metaclass;
規(guī)則二:類(lèi)的 super_class 指向其父類(lèi),如果該類(lèi)為根類(lèi)則值為 NULL娱节;
規(guī)則三:metaclass 的 isa 指向根 metaclass,如果該 metaclass 是根 metaclass 則指向自身祭示;
規(guī)則四:metaclass 的 super_class 指向父 metaclass肄满,如果該 metaclass 是根 metaclass 則指向該 metaclass 對(duì)應(yīng)的類(lèi);
無(wú)圖無(wú)真相!
那么 class 與 metaclass 有什么區(qū)別呢质涛?
class 是 instance object 的類(lèi)類(lèi)型稠歉。當(dāng)我們向?qū)嵗龑?duì)象發(fā)送消息(實(shí)例方法)時(shí),我們?cè)谠搶?shí)例對(duì)象的 class 結(jié)構(gòu)的 methodlists 中去查找響應(yīng)的函數(shù)汇陆,如果沒(méi)找到匹配的響應(yīng)函數(shù)則在該 class 的父類(lèi)中的 methodlists 去查找(查找鏈為上圖的中間那一排)怒炸。如下面的代碼中,向str 實(shí)例對(duì)象發(fā)送 lowercaseString 消息毡代,會(huì)在 NSString 類(lèi)結(jié)構(gòu)的 methodlists 中去查找 lowercaseString 的響應(yīng)函數(shù)横媚。
metaclass 是 class object 的類(lèi)類(lèi)型。當(dāng)我們向類(lèi)對(duì)象發(fā)送消息(類(lèi)方法)時(shí)月趟,我們?cè)谠擃?lèi)對(duì)象的 metaclass 結(jié)構(gòu)的 methodlists 中去查找響應(yīng)的函數(shù)灯蝴,如果沒(méi)有找到匹配的響應(yīng)函數(shù)則在該 metaclass 的父類(lèi)中的 methodlists 去查找(查找鏈為上圖的最右邊那一排)。如下面的代碼中孝宗,向 NSString 類(lèi)對(duì)象發(fā)送 stringWithString 消息穷躁,會(huì)在 NSString 的 metaclass 類(lèi)結(jié)構(gòu)的 methodlists 中去查找 stringWithString 的響應(yīng)函數(shù)。
練習(xí)
下面的代碼輸出什么?
@implementation Dog : Animal
- (instancetype)init{
self = [super init];
if (self) {
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end
runtime中- (Class)class方法實(shí)現(xiàn)如下
- (Class)class {
return object_getClass(self);
}
runtime中+ (Class)class方法實(shí)現(xiàn)如下
+ (Class)class {
return self;
}
打印結(jié)果: 都輸出Dog
2016-06-22 21:11:22.451 RuntimeTest[969:29418] IMP: -[NSObject(Animal) run]
2016-06-22 21:11:22.452 RuntimeTest[969:29418] IMP: -[NSObject(Animal) run]
問(wèn): 為什么?
下面的代碼輸出什么?
BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Animal class] isKindOfClass:[Animal class]];
BOOL res4 = [[Animal class] isMemberOfClass:[Animal class]];
Animal *animal = [[Animal alloc] init];
BOOL res5 = [animal class] == [Animal class];
BOOL res6 = [animal isKindOfClass:[Animal class]];
BOOL res7 = [animal isMemberOfClass:[Animal class]];
NSLog(@"%d %d %d %d %d %d %d", res1, res2, res3, res4, res5, res6, res7);
runtime中isKindOfClass實(shí)現(xiàn)如下
- (BOOL)isKindOf:aClass
{
Class cls;
for (cls = isa; cls; cls = cls->superclass)
if (cls == (Class)aClass)
return YES;
return NO;
}
isMemberOfClass實(shí)現(xiàn)如下
- (BOOL)isMemberOf:aClass
{
return isa == (Class)aClass;
}
打印輸出:
2016-06-22 21:15:13.840 RuntimeTest[987:31071] 1 0 0 0 1 1 1
問(wèn): 為什么?
下面的代碼輸出什么
@interface NSObject (Animal)
+ (void)run;
@end
@implementation NSObject (Animal)
- (void)run
{
NSLog(@"IMP: -[NSObject(Animal) run]");
}
@end
[NSObject run];
[[NSObject new] run];
打印輸出:
2016-06-22 21:19:31.619 RuntimeTest[997:33664] IMP: -[NSObject(Animal) run]
2016-06-22 21:19:31.620 RuntimeTest[997:33664] IMP: -[NSObject(Animal) run]
問(wèn):為什么?