下面是一道比较经典的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 Meta
的SuperClass
中查找父类中是否有Say
方法,还是没有~ 再看Son Meta
的SuperClass
3.然后找到NSObject Meta
中还是没找到Say
,再看NSObject Meta
的SuperClass
4.关键在这里,NSObject Meta
的 Superclass
指向 NSObject class
,而 NSObject Category
当中实现了Say
方法,所以打印成功。
从结果反证结论是没问题的,但是明明调用的是 类方法,为什么会调用到NSObject
中的 实例方法呢?
下回再分析
网友评论