小码哥底层原理笔记:Runtime之super指针

我们先创建两个类Person和Student,Student继承自Person类,接下来我们在Student打印如下代码:

@implementation Student

- (void)run{
    [super run];
    NSLog(@"Student");
}

- (instancetype)init{
    if (self = [super init]) {
        NSLog(@"[self class] = %@",[self class]);//Student
        NSLog(@"[self superclass] = %@",[self superclass]);//Person
        NSLog(@"----------------------");
        NSLog(@"[super class] = %@",[super class]);//Student
        NSLog(@"[super superclass] = %@",[super superclass]);//Person
    }
    return self;
}

@end

发现super跟self好像效果都是一样的。这是什么原因,那我们就需要去看看super方法的底层调用了。我们看下run方法底层是怎样的?

- (void)run{
    [super run];
    NSLog(@"Student");
}
struct __rw_objc_super arg = {
    (id)self,//消息接收者
    (id)class_getSuperclass(objc_getClass("Student"))//消息接收者的父类
    };
    
    objc_msgSendSuper(arg,
                      @selector(run));

可以看到super是通过objc_msgSendSuper发送消息,其中arg中消息接收者还是self。传进去的那个父类是表示直接从父类去查找方法,而不是跟往常一样从当前对象查找。那么[super class]就是直接从父类Person去搜索,而class方法在NSObject里面,class的底层实现是这样

- (Class)class{
 return object_getClass(self);
}

class调用返回值取决于方法接收者self跟父类无关,所以打印的还是Student。

superClass的底层实现是这样:

+ (id)superclass
{ 
    return self->superclass; 
}

- (id)superclass
{ 
    return isa->superclass; 
}

其实返回的就是消息接收者的父类

总结:super的本质是:(1)消息接收者还是当前对象,并不是父类。(2)super方法调用时是直接从父类去查找方法,而不是从当前对象开始查找

isMemberOfClass和isKindOfClass区别

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

很明显isMemberOfClass是判断当前对象是否是这个类对象。

isKindOfClass稍微复杂一点,首先是拿当前对象的类对象去比较看是否相等,如果不相等就跟父类比,直到NSObject基类。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容