专栏名称: Adrenine
iOS开发
目录
相关文章推荐
51好读  ›  专栏  ›  Adrenine

Objective C 中Self 和 Super 详解

Adrenine  · 掘金  ·  · 2017-12-13 08:46

正文

在 Objective-C 中的类实现中经常看到这两个关键字 ”self” 和 ”super”,以以前 oop 语言的经验,拿 c++ 为例,self 相当于 this,super 相当于调用父类的方法,这么看起来是很容易理解的。以下面的代码为例:

@interface Person:NSObject {  
    NSString*  name;  
}  
- (void) setName:(NSString*) yourName;  
@end  
 
@interface PersonMe:Person {  
    NSUInteger age;  
}  
- (void) setAge:(NSUInteger) age;  
- (void) setName:(NSString*) yourName andAge:(NSUInteger) age;  
@end  
 
@implementation PersonMe  
- (void) setName:(NSString*) yourName andAge:(NSUInteger) age {  
    [self setAge:age];  
    [super setName:yourName];  
}  
@end  
 
int main(int argc, char* argv[]) {  
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]  
    PersonMe* me = [[PersonMe alloc] init];  
    [me setName:@"asdf" andAge:18];  
    [me release];  
    [pool drain];  
    return 0;  
} 

上面有简单的两个类,在子类PersonMe中调用了自己类中的setAge和父类中的setName,这些代码看起来很好理解,没什么问题。 然后我在setName:andAge的方法中加入两行:

NSLog(@"self ' class is %@", [self class]);  
NSLog(@"super' class is %@", [super class]); 

这样在调用时,会打出来这两个的class,先猜下吧,会打印出什么?按照以前oop语言的经验,这里应该会输出:

self ' s class is PersonMe  
super ' s class is Person 

但是编译运行后,可以发现结果是:

self 's class is PersonMe  
super ' s class is PersonMe 

self 的 class 和预想的一样,怎么 super 的 class 也是 PersonMe?

真相

self 是类的隐藏的参数,指向当前当前调用方法的类,另一个隐藏参数是 _cmd,代表当前类方法的 selector。这里只关注这个 self。super 是个啥?super 并不是隐藏的参数,它只是一个“编译器指示符”,它和 self 指向的是相同的消息接收者,拿上面的代码为例,不论是用 [self setName] 还是 [super setName],接收“setName”这个消息的接收者都是 PersonMe* me 这个对象。不同的是,super 告诉编译器,当调用 setName 的方法时,要去调用父类的方法,而不是本类里的。

当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法

One more step

这种机制到底底层是如何实现的?其实当调用类方法的时候,编译器会将方法调用转成一个 C 函数方法调用,Apple 的 objcRuntimeRef 上说:

Sending Messages

When it encounters a method invocation, the compiler might generate a call to any of several functions to perform the actual message dispatch, depending on the receiver, the return value, and the arguments. You can use these functions to dynamically invoke methods from your own plain C code, or to use argument forms not permitted by NSObject’s perform… methods. These functions are declared in /usr/include/objc/objc-runtime.h.

objc_msgSend sends a message with a simple return value to an instance of a class.

objc_msgSend_stret sends a message with a data-structure return value to an instance of a class.







请到「今天看啥」查看全文


推荐文章
不正常人类研究中心  ·  除了人类,任何生物腿短都可爱。小短腿好萌!
8 年前
家教智慧  ·  女人,胖一点才好,不信你看!
8 年前
秦朔朋友圈  ·  “供股”后出老千怎么分辨?
7 年前