isa和superclass

isa指针

#import 

@interface MJPerson : NSObject 

+ (void)personClassMethod;
- (void)personInstanceMethod;

@end

@implementation MJPerson

+ (void)personClassMethod
{
    
}

- (void)personInstanceMethod
{
    
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJPerson *person = [[MJPerson alloc] init];
        [person personInstanceMethod];
        
        [MJPerson personClassMethod];
    }
    return 0;
}

将Objective-c代码转换成 C\C++的代码

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpps

找到[person personInstanceMethod];的 C++实现

((void (*)(id, SEL))(void *)objc_msgSend)((id)person, sel_registerName("personInstanceMethod"));

找到[MJPerson personClassMethod];的 C++实现

((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("MJPerson"), sel_registerName("personClassMethod"));

可以看出对象方法 C++实现是对instance对象发送一个方法消息,类方法 C++实现是对class对象发送一个方法消息。

但是对象方法是存放在class对象中,类方法是存放在meta-class对象中。也就是说instance对象找到class对象中的对象方法,class对象找到meta-class对象中的类方法。

isa和superclass_第1张图片
isa指针
  1. 当调用对象方法时,通过instance对象的isa指针找到class对象,最后找到对象方法的实现进行调用
  2. 当调用类方法时,通过class对象的isa指针找到meta-class对象,最后找到类方法的实现进行调用

superclass指针

#import 

@interface MJPerson : NSObject 

+ (void)personClassMethod;
- (void)personInstanceMethod;

@end

@implementation MJPerson

+ (void)personClassMethod
{
    
}

- (void)personInstanceMethod
{
    
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

@end

@interface MJStudent : MJPerson 

+ (void)studentClassMethod;
- (void)studentInstanceMethod;

@end

@implementation MJStudent

+ (void)studentClassMethod
{
    
}

- (void)studentInstanceMethod
{
    
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    
}

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder
{
    return nil;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MJStudent *student = [[MJStudent alloc] init];
        
        [student personInstanceMethod];
        
        [MJStudent personClassMethod];
    }
    return 0;
}

找到[student personInstanceMethod];的 C++实现

((void (*)(id, SEL))(void *)objc_msgSend)((id)student, sel_registerName("personInstanceMethod"));

找到[MJStudent personClassMethod];的 C++实现

((void (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("MJStudent"), sel_registerName("personClassMethod"));

[student personInstanceMethod];通过isa指针只能找到MJStudentclass对象,但是personInstanceMethod存储在MJPersonclass对象中。

[MJStudent personClassMethod];通过isa指针只能找到MJStudentmeta-class对象,但是personClassMethod存储在MJPersonmeta-class对象中。

这就需要MJStudentclass对象找到MJPersonclass对象中的对象方法,MJStudentmeta-class对象找到存储在MJPersonmeta-class对象中的类方法。

isa和superclass_第2张图片
superclass

MJStudentinstance对象要调用MJPerson的对象方法时,会先通过isa找到MJStudentclass对象,然后通过superclass找到MJPersonclass对象,最后找到对象方法的实现进行调用。

isa和superclass_第3张图片
superclass

MJStudentclass对象要调用MJPerson的类方法时,会先通过isa找到MJStudentmeta-class对象,然后通过superclass找到MJPersonmeta-class对象,最后找到类方法的实现进行调用。

isa 、superclass总结

isa和superclass_第4张图片
isa 、superclass总结
  1. instance对象的isa指向class对象
  2. class对象的isa指向meta-class对象
  3. meta-class对象的isa指向基类的meta-class对象
  4. class对象的superclass指向父类的class对象

    如果没有父类,superclass指针为nil

  5. meta-class对象的superclass指向父类的meta-class对象

    基类的meta-class对象的superclass指向基类的class对象

  6. instance对象调用方法的轨迹

    isaclass对象,方法不存在,就通过superclass找父类
    最后方法不存在报错unrecognized selector send to instance *****

  7. class对象调用类方法的轨迹

    isameta-clas对象,方法不存在,就通过superclass找父类
    最后方法不存在报错unrecognized selector send to class *****

代码验证基类的meta-class对象的superclass指向基类的class对象
Nsobject的分类

#import "NSObject+test.h"

@implementation NSObject (test)

+ (void)test
{
    NSLog(@"+[NSObject test]----%p", self);
}

@end

main文件的代码

#import 
#import "NSObject+test.h"

@interface MJPerson : NSObject

+ (void)test;

@end

@implementation MJPerson

+ (void)test
{
    NSLog(@"+[MJPerson test]----%p", self);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"[MJPerson class]---%p", [MJPerson class]);
        NSLog(@"[NSObject class]---%p", [NSObject class]);
        
        [MJPerson test];
        [NSObject test];
    }
    return 0;
}

打印结果

验证

结果看出MJPersonclass对象调用+[MJPerson test]方法,NSObjectclass对象调用+[NSObject test]方法。

注释掉MJPerson类的+ (void)test;方法

#import 
#import "NSObject+test.h"

@interface MJPerson : NSObject

+ (void)test;

@end

@implementation MJPerson

//+ (void)test
//{
//    NSLog(@"+[MJPerson test]----%p", self);
//}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"[MJPerson class]---%p", [MJPerson class]);
        NSLog(@"[NSObject class]---%p", [NSObject class]);
        
        [MJPerson test];
        [NSObject test];
    }
    return 0;
}

打印结果

验证

结果看出MJPersonclass对象调用+[NSObject test]方法,NSObjectclass对象调用+[NSObject test]方法。

再注释掉NSObject类的- (void)test方法,添加- (void)test方法

#import "NSObject+test.h"

@implementation NSObject (test)

//+ (void)test
//{
//    NSLog(@"+[NSObject test]----%p", self);
//}

- (void)test
{
    NSLog(@"-[NSObject test]----%p", self);
}

@end

打印结果

验证

结果看出MJPersonclass对象调用-[NSObject test]方法,NSObjectclass对象调用-[NSObject test]方法。但是- (void)test方法是存放在NSObjectclass对象中,也就证明了基类的meta-class对象的superclass指向基类的class对象

你可能感兴趣的:(isa和superclass)