上图可以得知
每个类都有自己特有的类对象、元类,父子类的类对象、元类也为父子关系。
类对象的父类最终会指向nil,而元类的父类最终指向了根的类对象。
有如下代码:
@interface NSObject (sport)
/// 给NSObject添加类方法声明
+(void)run;
@end
@implementation NSObject (sport)
/// 实现却是实例方法
- (void)run {
NSLog(@"run.....");
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
// 调用
[NSObject run];
}
输出:
2020-07-01 15:49:04.075158+0800 Demo[7175:1743450] run.....
明明调用的是NSObject的类方法,但是最终却调用到了实例方法,why……
结合上图,NSObject就是根类对象Root class(class)
,当调用[NSObject run]
时会根据其isa
指针找到根元类Root class(meta)
,但是根元类中并没有方法run
方法(元类中只会储存类方法的实现),接着会到根元类的父类根类对象Root class(class)
中查找,而其中确有run
方法,就这样实例方法被调用到了。
实际上所有NSObject的实例方法都可以通过调用类方法的形式进行调用,并且如下可以调用:
[UIViewController run];
[UIColor run];
[UIButton run];
但是注意一下情况:
@interface UIViewController (sport)
+ (void)jump;
@end
@implementation UIViewController (sport)
- (void)jump {
NSLog(@"jump.....");
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
// 调用
[UIViewController jump];
}
此时[UIViewController jump]
就会crash,UIViewController
相当于上图中的类对象Superclass(class)
,调用jump
会去其isa指向的元类Superclass(meta)
中寻找-没有,去元类的父类Root class(meta)
寻找-没有,再去其父类Root class(class)
寻找也没有,因为jump
方法是在类对象Superclass(class)
中保存的,最终crash掉。
网友评论