前兩天碰到一面試題:
//分辨下面res的是非
BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Sark class] isKindOfClass:[Sark class]];
BOOL res4 = [[Sark class] isMemberOfClass:[Sark class]];
在這之前,我們先了解一下相關(guān)的定義:
Class
在objc.h
中Class
是這么定義的:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
objc_class
又是啥呢朱嘴?在runtime.h
中能看見:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
MetaClass
上面能看到Class
中有個(gè)isa
參數(shù)莫湘,它是指向Class
的元類(MetaClass)
的指針尤蒿。
注意到isa
也是一個(gè)Class
的結(jié)構(gòu)體,也就是說MetaClass
其本質(zhì)也是一個(gè)Class
逊脯。
我們可以把Meta Class理解為 一個(gè)Class對象的Class优质。簡單的說:
- 當(dāng)我們發(fā)送一個(gè)消息給一個(gè)NSObject對象時(shí),這條消息會在對象的類的方法列表里查找
- 當(dāng)我們發(fā)送一個(gè)消息給一個(gè)類時(shí),這條消息會在類的Meta Class的方法列表里查找
之后就有了下面的這張圖:
能看到:
- 每個(gè)
Class
都有一個(gè)isa
指針指向一個(gè)唯一的MetaClass
- 每一個(gè)
MetaClass
的isa
指針都指向最上層的MetaClass
(圖中的NSObject
的MetaClass
) - 最上層的
MetaClass
的isa
指針指向自己巩螃,形成一個(gè)回路 - 每一個(gè)
MetaClass
的super class
指針指向它原本Class
的Super Class
的MetaClass
演怎。 - 最上層的
MetaClass
的Super Class
指向NSObject
Class
本身 - 最上層的
NSObject
Class
的super class
指向nil
接下來我們看看objc
源碼中(源碼可到這里下載),在文件Object.mm
內(nèi)避乏,上面相關(guān)方法的定義:
+ (Class)class {
return self;
}
- (BOOL)isKindOf:aClass
{
Class cls;
for (cls = isa; cls; cls = cls->superclass)
if (cls == (Class)aClass)
return YES;
return NO;
}
- (BOOL)isMemberOf:aClass
{
return isa == (Class)aClass;
}
那么爷耀,BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
就可以這樣對應(yīng)起來理解了:
[NSObject class]
拿到的是self
,類方法的return self
,即上圖紫色的NSObject(Class)
拍皮。
根據(jù)上面- (BOOL)isKindOf:aClass
的實(shí)現(xiàn)歹叮,for
循環(huán)首先拿到的cls = isa
,也就是cls
為NSObject(Class)
的MetaClass
。顯然這時(shí)候cls == (Class)aClass
不成立铆帽。
隨后咆耿,cls = cls->superclass
,即cls
變成了NSObject(Class)
的MetaClass
的superclass
,根據(jù)圖示可以爹橱,superclass
指向的是NSObject(Class)
萨螺,至此cls == (Class)aClass
成立,返回YES
愧驱。
同樣的道理慰技,分析BOOL res3 = [[Sark class] isKindOfClass:[Sark class]];
:
[Sark class]
拿到的是Sark(Class)
,而- (BOOL)isKindOf:aClass
中cls
拿到的值依次是Sark Meta Class
->NSObject Meta Class
->NSObject Class
-> nil
,沒有相等的,return NO
组砚。
剩下兩個(gè)吻商,根據(jù)- (BOOL)isMemberOf:aClass
的實(shí)現(xiàn),很容易得出結(jié)論會return NO
糟红。
喜歡我的可以關(guān)注收藏我的個(gè)人博客:Ro.bber