美文网首页
isKindOfClass & isMemberOfClass

isKindOfClass & isMemberOfClass

作者: 吕建雄 | 来源:发表于2020-09-19 16:50 被阅读0次

    下面两段代码,输出结果是否符合预期呢?

    BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];//<1>

    BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];//<2>

    BOOL res3 = [[LTClass class] isKindOfClass:[LTClass class]];//<3>

    BOOL res4 = [[LTClass class] isMemberOfClass:[LTClass class]];//<4>

    NSLog(@"res1=%hhd,res2=%hhd,res3=%hhd,res4=%hhd",res1,res2,res3,res4);

    BOOL res5 = [[NSObject alloc] isKindOfClass:[NSObject class]];//<5>

    BOOL res6 = [[NSObject alloc] isMemberOfClass:[NSObject class]];//<6>

    BOOL res7 = [[LTClass alloc] isKindOfClass:[LTClass class]];//<7>

    BOOL res8 = [[LTClass alloc] isMemberOfClass:[LTClass class]];//<8>

    NSLog(@"res5=%hhd,res6=%hhd,res7=%hhd,res8=%hhd",res5,res6,res7,res8);

    对象、类、元类的关系图(虚线为iSA,实线为继承关系)  图1

    上图中,Root class(class)其实就是NSObject

    objc源码来揭开其真实的底层逻辑:

    isKindOfClass类方法

    通过源码(截图代码来自Apple的objc源码),在类方法isKindOfClass中有一个循环,先判断class是否等于meta class,不等就判断是否等于meta class的superclass,不等就继续取superclass,如此循环下去

    对应到代码<1>中

    [NSObject class],NSObject调用类方法class返回self(即:NSObject);

    将NSObject与NSObject->iSA(即:NSObject meta class 元类)进行比较,NSObject不等于NSObject meta class;

    继续取NSObject meta class的superclass,由上面的关系图可知,NSObject meta class的superclass为NSObject;那么此时NSOjbect==NSObject,所以返回YES

    对应到代码<3>中:

    将LTClass与LTClass->iSA(即:LTClass meta class)进行比较,二者不相等;

    继续取LTClass meta class的superclass(即:NSObject meta class)进行比较,LTClass与NSObject meta class不相等

    继续取NSObject meta class的superclass(即:NSObject),LTClass与NSObject不相等

    继续取NSObject的superclass(即:nil),LTClass与nil不相等;至此循环结束,返回NO

    class类方法 isMemberOfClass类方法

    isMemberOfClass的类方法可知,是判断当前类的meta class 与 class进行比较(即:将自己与自己的iSA进行比较)

    对应到代码<2>中:将NSObject 的meta class与NSObject比较,不相等,所以返回NO

    对应到代码<4>中:将NTClass 的meta class与NTClass比较,不相等,所以返回NO

    isKindOfClass实例方法 class实例方法 object_getClass方法

    通过源码可知:实例方法isKindOfClass中同样是有一个循环,先调用实例的class方法,class方法调用object_getClass(self)方法,object_getClass方法返回obj->getIsa()即:返回实例对象的iSA对象也就是类

    对应到代码<5>中:[NSObject alloc]返回NSObject的实例,进入到isKindOfClass方法中,

    首先通过NSObject的实例的class方法获取到类(即:NSObject),[NSObject class]直接返回NSObject;NSObject与NSObject相等,结束循环,返回YES

    对应到代码<7>中:[LTClass alloc]返回LTClass的实例,进入到isKindOfClass方法中,

    首先通过NTClass的实例的class方法获取到类(即:NTClass),[NTClass class]直接返回NTClass,NTClass与NTClass相等,结束循环,返回YES

    isMemberOfClass实例方法

    通过源码可知:实例方法isMemberOfClass是通过实例调用class方法,然后调用object_getClass方法返回类;然后将返回的类与目标类进行比较;

    对应到代码<6>中:[NSObject alloc]返回NSObject的实例,进入到isMemberOfClass方法中,

    通过NSObject的实例的class方法获取到类(即:NSObject),[NSObject class]直接返回NSObject, NSObject与NSObject相等,返回YES

    对应到代码<8>中:[LTClass alloc]返回NTClass的实例,进入到isMemberOfClass方法中,

    通过NTClass的实例的class方法获取到类(即:LTClass),[LTClass class]直接返回LTClass,LTClass与LTClass相等,返回YES

    综上分析:

    类方法isKindOfClass,先获取类对象的iSA即元类,元类继承链与指定类对比

    实例方法isKindOfClass,先获取实例对象的iSA即类,类继承链与指定类对比

    类方法isMemberOfClass,先获取类对象的iSA即元类,元类与指定类对比

    实例方法isMemberOfClass,先获取实例对象的iSA即类,类与指定类对比

    代码<1>到代码<8>输出的结果为:

    1000

    1111

    相关文章

      网友评论

          本文标题:isKindOfClass & isMemberOfClass

          本文链接:https://www.haomeiwen.com/subject/juieyktx.html