目录
二 为什么基类的metaclass 的superclass 指向的是基类的类
总结如下:
- instance 的isa 指向是class
- class 的isa 指向是metaclass
- metaclass 的isa指向是基类的imetaclass
- class 的superclass 指向的是父类的class
- class如果没有父类,superclass 指向的是nil
- metaclass 的superclass 指向的是父类的metaclass
- 基类的metaclass 的superclass 指向的是基类的类
1 所以实例对象方法的调用轨迹是
isa 找到class,通过superclass 一直往上寻找,直到找到对应的方法,如果找不到,就结束,抛出异常
2 类对象方法调用的轨迹是
isa 找到metaclass,方法不存在,通过superclass 一直寻找,如果找不到,就结束,抛异常
二 为什么基类的metaclass 的superclass 指向的是基类的类
Person 类的类方法和 NSObject 类的类方法都没有实现,但是Person 类 和 NSObject 调用类方法却没有崩溃产生?
从上图可以看出来
正式因为metaclass的superclass 指向的是基类的类,因为基类中有同名的test 方法,所以没有崩溃产生。
因为代码的本质是
[Person test];
objc_msgsend([Person class],@selector(test));
只是告诉给这个类发送消息,调用test方法,并没有告知是+ 方法 或者 - 方法
oc 调用方法的本质就是通过方法名字去寻找,不会区分类方法和实例对象方法
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSObject (Test)
+ (void)test;
@end
NS_ASSUME_NONNULL_END
#import "NSObject+Test.h"
@implementation NSObject (Test)
// 不实现NSObject 类的 类方法 test
//
//+ (void)test{
//
// NSLog(@"+[Person test] -- %p",self);
//}
// 但是实现NSObject 的对象方法
- (void)test{
NSLog(@"-[Person test] -- %p",self);
}
@end
#import <Foundation/Foundation.h>
#import "NSObject+Test.h"
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
// 不实现person 类的 类方法 test
//+ (void)test{
//
// NSLog(@"+[Person test] -- %p",self);
//}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
[Person test];
[NSObject test];
}
return 0;
}
三 isa 的细节问题
实例对象的isa 指向 class,那么isa 中存在的地址值是否就是class 的地址值呢?
其实在64位以前,确确实实isa的中存在的地址值就是class的地址值,但是在64位以后,要进行一次与运算,才能获取class 的地址值
但是superclass 指针是不存在这个问题的