01--方法本质03--面试题分析

对方法的探索,全篇分六个章节

01-方法本质-方法初探

02-方法本质-objc_msgSend的使用

03-方法本质-面试题分析

04-方法本质-lookUpImpOrForward 介绍

05-方法本质-消息查找流程

06-方法本质-消息转发流程

三、面试题分析

前言

本章节分析下面两类方法的区别

self.class 和 super.class

isKindOfClass 和 isMemberOfClass

[toc]

3.1 self.class 和 super.class

  • 测试代码

    - (instancetype)init {
        if (self = [super init]) {
            NSLog(@"self.class  : %@",self.class);
            NSLog(@"super.class : %@",super.class);
        }
        return self;
    }
    
  • 输出

    self.class  : SRStudent
    super.class : SRStudent
    
  • 分析

    1. class 方法有两个隐藏参数,一个 self,一个是 SEL
    2. super.class 调用的方法是 objc_msgSendSuper,消息接受者还是 self
    3. super.class 只是表示在方法查找的时候跳过从自己的方法列表中查找,直接从父类方法列表中开始查找;

3.2 isKindOfClass 和 isMemberOfClass

  • 方法源码

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

    1.先取比较对象的 cls
    * 如果是实例对象,则取的是 class,实例对象->类对象
    * 如果是类对象,则取的是元类,类对象->元类

    2.然后 遍历 clssuperclass
    * 如果匹配到相同的,直接返回 YES
    * 如果一直没匹配到相同,返回 NO

  • isMemberOfClass总结

    • 选取比较对象的 cls,直接跟被比较的对象比较
    • 相对于 isKindOfClass,不会去遍历 superclass 进行匹配。
    • 如果是实例对象,则取的是 class,实例对象->类对象,用类对象比较
    • 如果是类对象,则取的是元类,类对象->元类,用元类对象比较

3.2.1 类方法调用例子

  1. + (BOOL)isKindOfClass:(Class)cls 方法分析

    • 方法调用格式
      [A isKindOfClass:B]

      • A-tcls 初始值:A的元类
      • A-tcls 偏移值:A的元类的父类
      • B-cls:用来做比较的类

      A的元类/A的元类的父类/包括NSObject类 只要有 和B相同的即为真

    • 方法调用例子

      1. BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; // 1
        * A : NSObject元类/NSObject类
        * B : NSObject类
    A和B有一个相同的NSObject类,所以返回真
    
    2. BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];       // 0


        * A : LGPerson元类/NSObject元类/NSObject类
        * B : LGPerson类
    A和B没有一个相同的类,所以返回假
  1. + (BOOL)isMemberOfClass:(Class)cls 方法分析

    • 方法调用格式
      [A isMemberOfClass:B]

      • A-self:A的元类
      • B-cls:用来做比较的类
    • 方法调用例子

      1. BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]]; // 0
        * A : NSObject元类
        * B : NSObject类
        不相同,所以返回假
    2. BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];     // 0


        * A : LGPerson元类
        * B : LGPerson类
        不相同,所以返回假

3.2.2 对象方法调用例子

  1. - (BOOL)isKindOfClass:(Class)cls 方法分析

    • 方法调用格式
      [A isKindOfClass:B]

      • A-tcls 初始值:A的类
      • A-tcls 偏移值:A的类的父类
      • B-cls:用来做比较的类
    • 方法调用例子

      1. BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]]; // 1

        • A : NSObject类
        • B : NSObject类
      2. BOOL re7 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]]; // 1

        • A : LGPerson类/NSObject类
        • B : LGPerson类
  2. - (BOOL)isMemberOfClass:(Class)cls 方法分析

    • 方法调用格式
      [A isMemberOfClass:B]

      • A-self:A的类
      • B-cls:用来做比较的类
    • 方法调用例子

      1. BOOL re6 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]]; // 1

        • A : NSObject类
        • B : NSObject类
      2. BOOL re8 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]]; // 1

        * A : LGPerson类
        * B : LGPerson类

你可能感兴趣的:(01--方法本质03--面试题分析)