美文网首页IOS开发知识点
iOS一道元类面试题

iOS一道元类面试题

作者: 程序员学哥 | 来源:发表于2021-03-17 18:36 被阅读0次

    简单更新一道元类面试题
    题目就是:下面这个程序的输出的结果是什么?

    @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;
    }
    

    实际上答案就在下面这张图上:


    20180706222710673.png

    Class的结构如下所示:


    20180706223108421.png

    isa: 实例的isa指向Class,Class的isa指向对应的元类
    super_class: 指向父类的类指针
    name: 类的名字
    version: 类的版本
    info: 类的一些信息,什么信息不清楚
    instance_size: 实例变量的大小
    ivars: 类的成员变量
    methodLists: 保存类的成员方法
    cache: 保存最近调用的一些方法,用于优化方法查找
    protocols: 保存类实现的一些协议

    类的实例方法是存储在类的methodLists中
    而类方法则是存储在元类的methodLists中,

    因此根据上图,NSObject的元类的superclass是指向Class,当调用[NSObject test]的时候,因为这是一个类方法调用,所以从元类中查找签名为test的方法,没有发现,然后再沿superclass继续查找,结果在Class中查找到该方法,于是调用该方法输出。但如果将NSObject的分类,换成其他类的分类,如NSString,会发现程序崩溃,这是因为签名为test的函数在NSString中,而当我们进行类方法调用的时候,最后会查找到NSObject的Class中,但该Class中并没有对应的方法签名,于是再沿superclass向上查找,由于NSObject的superclass是nil,于是抛出unrecognized selector。

    相关文章

      网友评论

        本文标题:iOS一道元类面试题

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