runtime面试题

2019-03-15  本文已影响0人  来自蒙塔基的钢蛋儿

下面是一道比较经典的runtime问题:


@interface NSObject (say)

@end

@implementation NSObject (say)
- (void)say{
    NSLog(@"say");
}
@end

@interface Father : NSObject

@end

@implementation Father

@end

@interface Son : Father
+ (void)say;
@end
@implementation Son

@end

下面两行代码:

    [Son say];
    [[NSObject new] performSelector:@selector(say)];

哪行运行后会crash?


~
~
~
~
~
~
~
~
~
~

答案:

两个方法均可以正常运行
2019-03-15 18:32:58.773622+0800 myTest[65792:3582166] say
2019-03-15 18:32:58.773798+0800 myTest[65792:3582166] say
可以看到两个func say() 都没有直接实现但是确没有问题,很不符合常理


接下来我们从Class的继承实现分析一下原因

首先我先贴一张Class结构图:

结构图

网上随便找的图,接下来我们看一下他们的关系。

[Father实例] -----isa------>[Father Class]
-----isa------>[Father Meta]
-----isa------>[NSObject Meta]<-----isa------>[NSObject Meta]-----isa------>
[NSObject Class]

这是一个完整的继承链,下面Son代表[Son Class]:
1.Son 调用Say方法会去Son Meta中的MethodList中查找Say方法,结果肯定没有嘛~
2.接下来会去Son MetaSuperClass中查找父类中是否有Say方法,还是没有~ 再看Son MetaSuperClass
3.然后找到NSObject Meta中还是没找到Say,再看NSObject MetaSuperClass
4.关键在这里,NSObject MetaSuperclass 指向 NSObject class ,而 NSObject Category当中实现了Say方法,所以打印成功。


从结果反证结论是没问题的,但是明明调用的是 类方法,为什么会调用到NSObject中的 实例方法呢?
下回再分析

上一篇 下一篇

猜你喜欢

热点阅读