Skip to content

Instantly share code, notes, and snippets.

@hamartia0
Created September 16, 2017 16:24
Show Gist options
  • Save hamartia0/dc13170ff93e4953cd1353fc35b8a180 to your computer and use it in GitHub Desktop.
Save hamartia0/dc13170ff93e4953cd1353fc35b8a180 to your computer and use it in GitHub Desktop.
关于在类的继承中,super 关键字的含义和方法派发的不理解
//
// main.m
// AccessorMethodsDemo
//
// Created by 赵白杨 on 2017/9/14.
// Copyright © 2017年 赵白杨. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface BaseClass : NSObject
- (void)testMethod;
@end
@implementation BaseClass
- (instancetype)init {
if (self = [super init]) {
[self testMethod];
}
return self;
}
- (void)testMethod {
NSLog(@"Invocation by BaseClass");
}
@end
@interface SubClass : BaseClass
@end
@implementation SubClass
- (instancetype)init {
if (self = [super init]) {
/**
super 等同于 self;
objc_msgSendSuper(self, initSelector) 在SubClass 的父类 BaseClass 里面的方法列表里,查找 init 方法;
跳转到 BaseClass 的 init 方法实现;我的主要问题就在这里,BaseClass 的 init 方法中的 [super init] 语句,为什么还是会调用 NSObject 的 init 方法,而 [self testMethod] 方法则是调用 SubClass 的 testMethod 方法。
*/
[self testMethod];
}
return self;
}
- (void)testMethod {
NSLog(@"Invocation by SubClass");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
/**
虾神:对于下面的代码,我的理解是:初始化 SubClass 对象,会调用 [super init],编译器转换为 objc_msgSendSuper(self, @selector(init)); 这个时候指令会去找 BaseClass 的 init 方法的实现,在 BaseClass 里面会执行 [super init],我的问题就是:在 BaseClass 里的 init 方法中,因为接收者是 SubClass 对象,所以 [ super init ] 中的 super 被编译器转换时,objc_msgSendSuper(self, @selector(init)) 中的 self 还是 SubClass 对象,所以还是应该在 BaseClass 的方法列表里面找方法,也就是说走不到 NSObject 的 init 方法。事实上self是Base对象,但是如果 Sub 覆写了 Base 的一个实例方法 testMethod, 并且在 Sub 和 Base 的 init 方法里,都调用了 testMethod 方法,走到 Base 的 init 方法的时候,self 是 Base 的话,就应该是在 Base 的方法列表里面查找这个方法,但是实际上是执行的 Sub 方法列表里面的 testMethod 方法,这就是我觉得不理解的地方。
*/
__unused SubClass *son = [[SubClass alloc] init];
// 编译器转化代码
/**
class mySubClass = objc_getClass("SubClass");
SEL allowSelector = @seletor(alloc);
SubClass *son1 = obj_msgSend(myClass, allowSeletor);
SEL initSeletor = @selector(init);
SubClass *son2 = objc_msgSend(son1, initSeletor);
*/
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment