美文网首页
self和super区别

self和super区别

作者: woshishui1243 | 来源:发表于2018-03-27 19:43 被阅读6次

在objc中的类实现中经常看到这两个关键字”self”和”super”,但他们的区别表现在各个方面。
以下面的代码为例:

@interface Father:NSObject {   
        NSString*  name;  
 }  
 - (void)setName:(NSString*) yourName;  

@end  

 @interface Son:Father  {  
       NSUInteger age;  
 }  
- (void) setAge:(NSUInteger) age;  
 - (void) setName:(NSString*) yourName andAge:(NSUInteger) age;  
@end  
@implementation Son  
 - (void) setName:(NSString*) yourName andAge:(NSUInteger) age   {  
       [self setAge:age];  
        [super setName:yourName];  
 }  
@end  

 int main(int argc, char* argv[]) {  
     AutoreleasePool{  
        Son* son = [[Son alloc] init];  
        [son setName:@"aaa" andAge:18];  
    }  
    return 0;  
}  

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

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

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

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

self 's class is Son

super ' s class is Son

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

具体原因要看他们的内部实现机制是什么样的:

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

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

这种机制到底底层是如何实现的?
当使用[self setName]调用时,会使用objc_msgSend的函数,先看下objc_msgSend的函数定义:

 id objc_msgSend(id theReceiver, SEL theSelector, ...)

第一个参数是消息接收者,第二个参数是调用的具体类方法的selector,后面是selector方法的可变参数。我们先不管这个可变参数,以 [self setName:]为例,编译器会替换成调用objc_msgSend的函数调用,其中theReceiver是self,theSelector是 @selector(setName:),这个selector是从当前self的class的方法列表开始找的setName,当找到后把对应的 selector传递过去。

而当使用[super setName]调用时,会使用objc_msgSendSuper函数,看下objc_msgSendSuper的函数定义:

 id objc_msgSendSuper(struct objc_super *super, SEL op, ...)

第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的selector,先看下objc_super这个结构体是什么东西:

 struct objc_super {
    id receiver;
    Class superClass;
};

可以看到这个结构体包含了两个成员,一个是receiver,这个类似上面objc_msgSend的第一个参数receiver,第二个成员是记 录写super这个类的父类是什么,拿上面的代码为例,当编译器遇到Son里setName:andAge方法里的[super setName:]时,开始做这几个事:

1,构建objc_super的结构体,此时这个结构体的第一个成员变量receiver就是son,和self相同。而第二个成员变量superClass就是指类Father,因为Son的超类就是这个Father。

2,调用objc_msgSendSuper的方法,将这个结构体和setName的sel传递过去。函数里面在做的事情类似这样:从 objc_super结构体指向的superClass的方法列表开始找setName的selector,找到后再以 objc_super->receiver去调用这个selector,可能也会使用objc_msgSend这个函数,不过此时的第一个参数 theReceiver就是objc_super->receiver,第二个参数是从objc_super->superClass中找到 的selector

里面的调用机制大体就是这样了,以上面的分析,回过头来看开始的代码,当输出[self class]和[super class]时,是个怎样的过程。

当使用[self class]时,这时的self是Son,在使用objc_msgSend时,第一个参数是receiver也就是self,也是 Son* son这个实例。第二个参数,要先找到class这个方法的selector,先从Son这个类开始找,没有,然后到Son的父类 Father中去找,也没有,再去Father的父类NSObject去找,一层一层向上找之后,在NSObject的类中发现这个class方法,而 NSObject的这个class方法,就是返回receiver的类别,所以这里输出Son。

当使用[super class]时,这时要转换成objc_msgSendSuper的方法。先构造objc_super的结构体吧,第一个成员变量就是self, 第二个成员变量是Father,然后要找class这个selector,先去superClass也就是Father中去找,没有,然后去Father 的父类中去找,结果还是在NSObject中找到了。然后内部使用函数objc_msgSend(objc_super->receiver, @selector(class)) 去调用,此时已经和我们用[self class]调用时相同了,此时的receiver还是Son* son,所以这里返回的也是Son。

相关文章

  • Objective-C self与super的区别

    Objective-C self与super的区别 [self class] 和 [super class] 在当...

  • self、 superclass 、 super的区别

    self、 superclass 、 super的区别 self、 superclass 、 super self...

  • self和super的区别

    self和super的区别 self调用自己方法,super调用父类方法 self是类,super是预编译指令 [...

  • class

    1.[self class]和 [super class] self和super的区别: self是类的一个隐藏参...

  • self和super区别

    在objc中的类实现中经常看到这两个关键字”self”和”super”,但他们的区别表现在各个方面。以下面的代码为...

  • self和super区别

    self:调用自己方法,它是类super:调用父类方法,它是预编译指令【self class】和【super cl...

  • iOS self 和 super区别以及为什么要self = [

    //联系人:石虎QQ: 1224614774昵称:嗡嘛呢叭咪哄 一、self和super区别 区别:- self调...

  • iOS - 关键字self和super

    一、self 和 super 区别 self 是类,super 是预编译指令(就是给编译器看的,不是一个指针; 只...

  • 今日所学20151230

    1.self 和 super 区别 self:代表当前方法的调用者,可以是类也可以是实例对象 super:编译器指...

  • self和super的区别

    关于 self 和 super 在oc 中 的疑惑 与 分析 这个问题貌似很初级,但很容易让人忽略,me too ...

网友评论

      本文标题:self和super区别

      本文链接:https://www.haomeiwen.com/subject/slnscftx.html