Created
September 16, 2017 16:24
-
-
Save hamartia0/dc13170ff93e4953cd1353fc35b8a180 to your computer and use it in GitHub Desktop.
关于在类的继承中,super 关键字的含义和方法派发的不理解
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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