簡(jiǎn)單更新一道元類(lèi)面試題
題目就是:下面這個(gè)程序的輸出的結(jié)果是什么怕午?
@interface NSObject(Test)
+ (void) test;
@end
@implementation NSObject(Test)
- (void) test
{
NSLog(@"%@",NSStringFromSelector(_cmd));
return;
}
@end
int main(int argc, char * argv[]) {
@autoreleasepool {
[NSObject test];
[[NSObject new] test];
}
return 0;
}
實(shí)際上答案就在下面這張圖上:
Class的結(jié)構(gòu)如下所示:
isa: 實(shí)例的isa指向Class,Class的isa指向?qū)?yīng)的元類(lèi)
super_class: 指向父類(lèi)的類(lèi)指針
name: 類(lèi)的名字
version: 類(lèi)的版本
info: 類(lèi)的一些信息淹魄,什么信息不清楚
instance_size: 實(shí)例變量的大小
ivars: 類(lèi)的成員變量
methodLists: 保存類(lèi)的成員方法
cache: 保存最近調(diào)用的一些方法郁惜,用于優(yōu)化方法查找
protocols: 保存類(lèi)實(shí)現(xiàn)的一些協(xié)議
類(lèi)的實(shí)例方法是存儲(chǔ)在類(lèi)的methodLists中
而類(lèi)方法則是存儲(chǔ)在元類(lèi)的methodLists中,
因此根據(jù)上圖甲锡,NSObject的元類(lèi)的superclass是指向Class兆蕉,當(dāng)調(diào)用[NSObject test]的時(shí)候,因?yàn)檫@是一個(gè)類(lèi)方法調(diào)用缤沦,所以從元類(lèi)中查找簽名為test的方法虎韵,沒(méi)有發(fā)現(xiàn),然后再沿superclass繼續(xù)查找缸废,結(jié)果在Class中查找到該方法包蓝,于是調(diào)用該方法輸出驶社。但如果將NSObject的分類(lèi),換成其他類(lèi)的分類(lèi)测萎,如NSString亡电,會(huì)發(fā)現(xiàn)程序崩潰,這是因?yàn)楹灻麨閠est的函數(shù)在NSString中硅瞧,而當(dāng)我們進(jìn)行類(lèi)方法調(diào)用的時(shí)候份乒,最后會(huì)查找到NSObject的Class中,但該Class中并沒(méi)有對(duì)應(yīng)的方法簽名腕唧,于是再沿superclass向上查找或辖,由于NSObject的superclass是nil,于是拋出unrecognized selector四苇。