看代码:

@implementation Son : Father
- (id)init{ self = [super init];
if (self){
}
return self;
}

self是什么,super是什么

在动态方法中:self代表着”对象”; 
在静态方法中:self代表着”类”; 
一句话总结就是:self代表着当前方法的调用者;

self 和 super 是Objective-C提供的两个保留字。 但有根本区别,self是类的隐藏的参数变量,指向当前调用方法的对象(类也是对象,类对象),另一个隐藏参数是_cmd,代表当前类方法的selector。super并不是隐藏的参数,它只是一个”编译器指示符”。

[ super init] 做了什么

发送消息

Class  A
- reposition{
...
[self setOrigin:someX :someY];
...
}

A a= [a .. init];[a reposition]; 
方法体中 编译器将 
[self setOrigin:someX :someY]; 
其转换为

objc_msgSend(id self,SEL _cmd, …) 。self -> a 
此时 self 指代a 对象,方法从a 对应 类结构的 方法调度表中开始寻找,如果找不到,延继承链往 父类中寻找 。

同样如果 reposition 是类方法, self 指代 A 类对象。

Class  A
-reposition{
...
[super setOrigin:someX :someY];
...
}

[a reposition]; 方法体中编译器将

[super setOrigin:someX :someY]; 
其转换为

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 这个类的父类是什么,拿上面的代码为例,当编译器遇到 A 里

[super setOrigin:someX :someY] 
时,开始做这几个事:

构建 objc_super 的结构体,此时这个结构体的第一个成员变量 receiver 就是 a,和 self 相同。而第二个成员变量 superClass 就是指类 A的 superClass。

调用 objc_msgSendSuper 的方法,将这个结构体和

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

为什么要 self = [super init];

符合oc 继承类 初始化规范 super 同样也是这样, [super init] 去self 的super 中调用init super 调用 superSuper 的init 。直到根类 NSObject 中的init ,根类中init 负责初始化 内存区域 向里面添加 一些必要的属性,返回内存指针, 这样 延着继承链 初始化的内存指针 被从上 到 下 传递,在不同的子类中向块内存添加 子类必要的属性,直到 我们的 A 类中 得到内存指针,赋值给slef 参数, 在if (slef){//添加A 的属性 }

下面来看看这个:

@implementation Son : Father
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%@", NSStringFromClass([self class]));
NSLog(@"%@", NSStringFromClass([super class]));
}
return self;
}
@end

应该不难分析出 打印结果:

Son 
Son

当 发送 class 消息 时不管是 self 还是 super 其消息主体依然是 self ,也就是说 self 和 super 指向的 是同一个对象。只是 查找方法的位置 区别,一个从本类,一个从本类的超类。 
一般情况下 class 方法 只有在 根类 NSObject 中定义,极少情况有子类重写 class 方法, 
所以 [slef class] 和 [super class] 都是在 根类中 找方法实现, 消息接收主体 又都是 a 
如果重写可能会不一样。 
自然都打印出 Son

在来一个例子:

#import <Foundation/Foundation.h>

@interface EngineSuper : NSObject
-(void)printCurrentClass;
@end #import "EngineSuper.h" @implementation EngineSuper
-(void)printCurrentClass{ NSLog(@"=EngineSuper=======%@",[self class]);
}
@end @interface Engine : EngineSuper
-(void)printSupClass;
@end @implementation Engine -(void)printSupClass{
[super printCurrentClass];
} //调用:
Engine *engine = [[Engine alloc]init];
[engine printCurrentClass];//直接调用父类 方法,engine没重载 它 [engine printSupClass];//间接调用父类方法,

打印当然都是 :

Engine 
Engine

方法体中 self 始终指代 方法的接收者 及对象 engine。, 
换成 NSLog(@”=EngineSuper=======%@”,[super class]); 结果也是一样的。

super 就是个障眼法 发,编译器符号, 它可以替换成 [slef class],只不过 方法是从 self 的超类开始 寻找。

转自:这里

Objective-C语言--self和super关键字解析的更多相关文章

  1. java学习第02天(语言基础组成:关键字、标识符、注释、常量和变量)

    Java语言基础组成 1. 关键字 就是指的一些单词,这些单词被赋予了特殊的java含义,就不再叫单词了. 例如: class Demo{ public static void main(String ...

  2. Java 并发:volatile 关键字解析

    摘要: 在 Java 并发编程中,要想使并发程序能够正确地执行,必须要保证三条原则,即:原子性.可见性和有序性.只要有一条原则没有被保证,就有可能会导致程序运行不正确.volatile关键字 被用来保 ...

  3. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  4. 使用 Object.create 创建对象,super 关键字,class 关键字

    ECMAScript 5 中引入了一个新方法:Object.create().可以调用这个方法来创建一个新对象.新对象的原型就是调用 create 方法时传入的第一个参数: var a = {a: 1 ...

  5. Android的init过程(二):初始化语言(init.rc)解析

    Android的init过程(一) 本文使用的软件版本 Android:4.2.2 Linux内核:3.1.10 在上一篇文章中介绍了init的初始化第一阶段,也就是处理各种属性.在本文将会详细分析i ...

  6. (转)Java并发编程:volatile关键字解析

    转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...

  7. OC基础--self关键字&super关键字

    PS:OC中的self关键字可以与C#中的this关键字区分记忆,虽然区别还是很大的. OC中的super关键字指的是父类指针 一.self关键字必须了解的知识: 1.使用场合:只能用在方法中(对象方 ...

  8. Android的init过程(二):初始化语言(init.rc)解析【转】

    转自:http://www.cnblogs.com/nokiaguy/p/3164799.html Android的init过程(一) 本文使用的软件版本 Android:4.2.2 Linux内核: ...

  9. volatile关键字解析(转)

    volatile关键字解析 转载:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在J ...

随机推荐

  1. CF558E A Simple Task

    题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过5000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终的字符串 首 ...

  2. HTTP 请求头中的 X-Forwarded-For,X-Real-IP

     X-Forwarded-For 在使用nginx做反向代理时,我们为了记录整个的代理过程,我们往往会在配置文件中做如下配置: location / { 省略... proxy_set_header ...

  3. kubernetes lable 操作

    我们要给已创建的Pod“redis-master”添加一个标签role=master: $ kubectl label pod redis-master role=master 查看该Pod的Labe ...

  4. 利用 share code 插件同步代码片段

    利用 Settings Sync可以同步 VS code 配置,但它只能同步插件,利用  Settings Sync 再配合 share code 插件可以同步自定义代码片段,可以把 VS code ...

  5. Ubuntu16.04安装Zabbix3.2(快速安装教程)

    ubuntu16.04下zabbix安装和配置 上面这篇虽然是一样的,但是针对的版本有差异,版本差异,安装方式也就有差异,对要求的环境可能有所不同. 今天帮同事安装zabbix,按照如下几个步骤,就完 ...

  6. JS编写简单的弹窗插件(含有demo和源码)

    最近项目做完了 事情不是很多,今天正好也在调休,所以趁着这个时间研究了一下简易的JS弹窗功能,当然网上这块插件非常多,本人也没有仔细看网上的插件源码 只是凭着日常使用过的弹窗插件有这么多功能 来实现自 ...

  7. 【转】mysql交互式连接&非交互式连接

    交互式操作:通俗的说,就是你在你的本机上打开mysql的客户端,就是那个黑窗口,在黑窗口下进行各种sql操作,当然走的肯定是tcp协议. 非交互式操作:就是你在你的项目中进行程序调用.比如一边是tom ...

  8. 《MySQL:菜鸟入门系列》

    关于数据库相关知识,几乎是互联网从业者逃不开的一个必备技能,特别是对于DB.开发和测试童鞋来说,更显得重要... 关于MySQL,推荐如下几本书: 入门级:<MySQL必知必会> 进阶级: ...

  9. 20155317 王新玮《网络对抗技术》实验5 MSF基础应用

    20155317 王新玮<网络对抗技术>实验5 MSF基础应用 1. MS08_067安全漏洞 原理:攻击者利用受害者主机默认开放的SMB服务端口445,发送特殊RPC请求,通过MSRPC ...

  10. 20155331《网络对抗》 Exp9 Web安全基础

    20155331<网络对抗> Exp9 Web安全基础 实验过程 WebGoat 在终端中输入java -jar webgoat-container-7.0.1-war-exec.jar开 ...