美文网首页iOS面试题
super、isKindOfClass、isMemberOfCl

super、isKindOfClass、isMemberOfCl

作者: 再好一点点 | 来源:发表于2021-11-15 20:19 被阅读0次
    一. super作用

    Person类

    #import <Foundation/Foundation.h>
    @interface Person : NSObject
    @end
    
    #import "Person.h"
    @implementation Person
    @end
    

    Student类

    #import "Person.h"
    @interface Student : Person
    @end
    
    #import "Student.h"
    #import <objc/runtime.h>
    
    @implementation Student
    
    - (instancetype)init
    {
        if (self = [super init]) {
            NSLog(@"[self class] = %@", [self class]); // Student
            NSLog(@"[self superclass] = %@", [self superclass]); // Person
    
            // objc_msgSendSuper({self, [Person class]}, @selector(class));
            NSLog(@"[super class] = %@", [super class]); // Student
            NSLog(@"[super superclass] = %@", [super superclass]); // Person
        }
        return self;
    }
    
    @end
    

    将OC代码转成C/C++代码可以看到[super class]等于objc_msgSendSuper({self, [Person class]}, @selector(class));

    结合上述打印结果可以有如下结论:

    1. [super message]objc_msgSendSuper(...)的底层实现
      a) 消息接收者仍然是子类对象
      b) 从父类开始查找方法的实现
      因此可以知道[super message]的消息接收者(调用者)还是self,只不过是从父类的方法列表开始查找方法而已。
    二. isKindOfClass、isMemberOfClass

    以下几个log的结果是什么?

    NSLog(@"%d", [[NSObject class] isKindOfClass:[NSObject class]]);
    NSLog(@"%d", [[NSObject class] isMemberOfClass:[NSObject class]]);
    NSLog(@"%d", [[Person class] isKindOfClass:[Person class]]);
    NSLog(@"%d", [[Person class] isMemberOfClass:[Person class]]);
    
    //上边等同于下边
    NSLog(@"%d", [NSObject isKindOfClass:[NSObject class]]); // 1
    NSLog(@"%d", [NSObject isMemberOfClass:[NSObject class]]); // 0
    NSLog(@"%d", [Person isKindOfClass:[Person class]]); // 0
    NSLog(@"%d", [Person isMemberOfClass:[Person class]]); // 0
    

    猛一看这几个结果可能会有点蒙,需要分析isKindOfClass、isMemberOfClass的具体含义才可以弄明白以上结果。
    通过objc源码可以查看到以上两个方法的具体实现。分别有实例方法和类方法。

    - (BOOL)isMemberOfClass:(Class)cls {
        return [self class] == cls;
    }
    
    - (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    
    + (BOOL)isMemberOfClass:(Class)cls {
        return object_getClass((id)self) == cls;
    }
    
    
    + (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    

    a) - (BOOL)isMemberOfClass:(Class)cls直接拿到实例的类对象和传入的cls比较是否相等。
    b) - (BOOL)isKindOfClass:(Class)cls使用传入的cls和实例的类对象或者父类比较(父类仍是类对象)。
    c) + (BOOL)isMemberOfClass:(Class)cls使用元类对象和传入的cls比较是否相等。
    d) + (BOOL)isKindOfClass:(Class)cls使用传入的cls和元类对象或者父类比较(父类仍是元类对象)。

    通过上边对每个方法的具体的介绍可以做具体分析了,首先第一个:

    1. [[NSObject class] isKindOfClass:[NSObject class]]就是拿到NSObject这个类对象的元类对象和[NSObject class]比较,左边是NSObject元类对象,右边是NSObject类对象肯定不同,这时候继续循环比较,左边通过superclass找到NSObject这个元类对象的父类就是NSObject类对象,这个时候左右都是NSObject的类对象所以相同,返回YES。
    2. [[NSObject class] isMemberOfClass:[NSObject class]]就是拿到NSObject这个类对象的元类对象和[NSObject class]比较,左边是NSObject元类对象,右边是NSObject类对象肯定不同,返回NO。
    3. [[Person class] isKindOfClass:[Person class]]通过循环遍历左边Person元类对象的的父类分别为NSObject元类对象、NSObject类对象,右边为Person类对象,所以都不相同,返回NO。
    4. [[Person class] isMemberOfClass:[Person class]]拿到Person类对象的元类对象和[Person class]比较,左边为Person元类对象,右边为Person类对象,所以不相同,返回NO。

    相关文章

      网友评论

        本文标题:super、isKindOfClass、isMemberOfCl

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