self和super到底怎么用?
2015-08-20 15:28
363 查看
开发过程中遇到一个问题.
问题简化描述如下:
有一个UIView的子类(CTestLevel),实现了init方法和initWithFrame方法,只调用了CTestLevel的init,init中只调用了[super init] , 可为什么当前类的initWithFrame被调用了?不应该是调用父类吗?怎么调用了子类的initWithFrame?
如下:
初始化一个对象
2.设置断点,查看调用关系
3 查看堆栈
查看调用关系和堆栈,
testObjc调用了init方法,然后调用了UIView的init的方法,这没有问题,
因为CTestLevel的init方法调用了[super init];
堆栈中最上层为什么又调用了CTestLevel 的initWithFrame方法呢?
initWithFrame是UIView的指定初始化方法,按道理应该调用UIView的initWithFrame方法啊,为什么调用了CTestLevel的initWithFrame的初始化方法?
因为子类重写了initWithFrame,所以调用子类的initWithFrame?如果不重写就调用UIView的initWithFrame?
super self 都是什么意思?
这都是怎么一个逻辑,具体是怎么实现的?
先说明Objective-C的类图结构:
其中实心箭头表示继承关系,CTestLevel继承自UIView,UIView继承自UIResponder, …一直继承到NSObject.NSObject的父类为nil, 所有类变量到最终的父类都是nil.
虚线箭头表示所属关系:testObj属于CTestLevel类的对象,CTestLevel类属于CTestLevel元类的对象。所有的元类对象属于NSObject元类对象,NSObject元类对象属于自身.
代码说明Objective-C类的结构
Objective-C中所有的东西都是对象,即使是类,它也是一种对象。
testObj对象的如下表示:
objc_object 表示一个对象,其中的isa指向CTestLevel类
Class的结构体定义如下:
其中isa指向CTestLevel元类,super_class指向其父类UIView,ivars存放变量,methodLists方法列表,cache缓存方法,protocols类所遵循的协议。
self和super的含义,在Objective-C中self表示当前对象(就是这个testObj对象),类似于C++里面的this指针;
super其实是一个编译器指示符,在Runtime运行期这个关键词是不存在的。只是辅助编译器做了一些处理罢了,类似语法糖的东西。
如何向对象发消息
testObj对象可以调用(init,initWithFrame, setHidden等方法),具体是怎么做到的?
例如:
当[testObj init]这样发送消息的时候,会转化为 id objc_msgSend(id theReceiver, SEL theSelector, …)来调用。其中theReceiver表示testObj对象,theSelector表示init方法. …表示参数,这里参数为空。
简写成如下这样:obj_msgSend(testObj,init,”“)
如果是调用哪个initWithFrame的话,大体如下:
obj_msg_Send(testObj,@Selector(initWithFrame),frame)
那调用[super init]的时候,没有testObj这个对象了?怎么办?
[super init]会转化成如下的方法
id objc_msgSendSuper(struct objc_super *super, SEL op, …)
一个objc_super,它具体是什么呢?结构体定义如下:
里面也有一个receiver,这个receiver就是消息的接受者,这里是self,就是这个testObj对象!
superClass: self的父类,也就是UIView.
op:表示方法;这里就是init.
一句话:去父类里面找init方法,然后给testObj发消息。对,用当前对象,调用父类的方法。
self和super的区别,就是去哪里找方法的问题,接受消息的对象还是那个对象。
举个例子说明:
类的继承关系:
CTestLevel_3继承自CTestLevel_2,CTestLevel_2继承自CTestLevel_1,CTestLevel_1继承自UIView.
testObj是一个CTestLevel_3类型的对象。
CTestLevel_3实现了一个testLevel3方法,方法直接调用 : [super testLevel2];
CTestLevel_2实现了一个testLevel2方法,方法打印输出:NSStringFromClass([self class]);
因为testObj是一个CTestLevel_3的对象类型,所以输出结果[self class]是一个CTestLevel_3类型。等价于给CTestLevel_3类型的对象,发送父类的testLevel2消息。
经常遇到下面的问题:
完。
问题简化描述如下:
有一个UIView的子类(CTestLevel),实现了init方法和initWithFrame方法,只调用了CTestLevel的init,init中只调用了[super init] , 可为什么当前类的initWithFrame被调用了?不应该是调用父类吗?怎么调用了子类的initWithFrame?
如下:
初始化一个对象
CTestLevel *testObj = [CTestLevel alloc] init];
@implementation CTestLevel - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { NSLog(@"initWithFrame"); } return self; } -(instancetype)init { self = [super init]; if (self) { NSLog(@"init"); } return self; } @end
2.设置断点,查看调用关系
3 查看堆栈
查看调用关系和堆栈,
testObjc调用了init方法,然后调用了UIView的init的方法,这没有问题,
因为CTestLevel的init方法调用了[super init];
堆栈中最上层为什么又调用了CTestLevel 的initWithFrame方法呢?
initWithFrame是UIView的指定初始化方法,按道理应该调用UIView的initWithFrame方法啊,为什么调用了CTestLevel的initWithFrame的初始化方法?
因为子类重写了initWithFrame,所以调用子类的initWithFrame?如果不重写就调用UIView的initWithFrame?
super self 都是什么意思?
这都是怎么一个逻辑,具体是怎么实现的?
先说明Objective-C的类图结构:
其中实心箭头表示继承关系,CTestLevel继承自UIView,UIView继承自UIResponder, …一直继承到NSObject.NSObject的父类为nil, 所有类变量到最终的父类都是nil.
虚线箭头表示所属关系:testObj属于CTestLevel类的对象,CTestLevel类属于CTestLevel元类的对象。所有的元类对象属于NSObject元类对象,NSObject元类对象属于自身.
代码说明Objective-C类的结构
Objective-C中所有的东西都是对象,即使是类,它也是一种对象。
testObj对象的如下表示:
/// Represents an instance of a class. struct objc_object { Class isa OBJC_ISA_AVAILABILITY; };
objc_object 表示一个对象,其中的isa指向CTestLevel类
Class的结构体定义如下:
typedef struct objc_class *Class; struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
其中isa指向CTestLevel元类,super_class指向其父类UIView,ivars存放变量,methodLists方法列表,cache缓存方法,protocols类所遵循的协议。
self和super的含义,在Objective-C中self表示当前对象(就是这个testObj对象),类似于C++里面的this指针;
super其实是一个编译器指示符,在Runtime运行期这个关键词是不存在的。只是辅助编译器做了一些处理罢了,类似语法糖的东西。
如何向对象发消息
testObj对象可以调用(init,initWithFrame, setHidden等方法),具体是怎么做到的?
例如:
当[testObj init]这样发送消息的时候,会转化为 id objc_msgSend(id theReceiver, SEL theSelector, …)来调用。其中theReceiver表示testObj对象,theSelector表示init方法. …表示参数,这里参数为空。
简写成如下这样:obj_msgSend(testObj,init,”“)
如果是调用哪个initWithFrame的话,大体如下:
obj_msg_Send(testObj,@Selector(initWithFrame),frame)
那调用[super init]的时候,没有testObj这个对象了?怎么办?
[super init]会转化成如下的方法
id objc_msgSendSuper(struct objc_super *super, SEL op, …)
一个objc_super,它具体是什么呢?结构体定义如下:
struct objc_super { id receiver; Class superClass; };
里面也有一个receiver,这个receiver就是消息的接受者,这里是self,就是这个testObj对象!
superClass: self的父类,也就是UIView.
op:表示方法;这里就是init.
一句话:去父类里面找init方法,然后给testObj发消息。对,用当前对象,调用父类的方法。
self和super的区别,就是去哪里找方法的问题,接受消息的对象还是那个对象。
举个例子说明:
类的继承关系:
CTestLevel_3继承自CTestLevel_2,CTestLevel_2继承自CTestLevel_1,CTestLevel_1继承自UIView.
testObj是一个CTestLevel_3类型的对象。
CTestLevel_3实现了一个testLevel3方法,方法直接调用 : [super testLevel2];
CTestLevel_2实现了一个testLevel2方法,方法打印输出:NSStringFromClass([self class]);
因为testObj是一个CTestLevel_3的对象类型,所以输出结果[self class]是一个CTestLevel_3类型。等价于给CTestLevel_3类型的对象,发送父类的testLevel2消息。
经常遇到下面的问题:
NSLog(@"%@\n",self); //CTestLevel_3 NSLog(@"%@\n",[self class]);//CTestLevel_3 NSLog(@"%@\n",[self superclass]);//CTestLevel_2 NSLog(@"%@\n",[[self class] superclass]);//CTestLevel2 class NSLog(@"%@\n",[super class]);//CTestLevel3 NSLog(@"%@\n",[super superclass]);//CTestLevel2
完。
相关文章推荐
- Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
- cocosbuilder
- Maven多模块依赖
- hbase实现分页查询
- 【博乐】把C币,装进你的口袋
- RS交叉表按照预定的节点成员排序
- Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
- chrome调试文章
- linux 一天一个命令之'cut'
- 发布IOS产品被拒后如何再上传新发布包
- JSP页面呈现HTML效果不正确的问题
- css基础精华01
- SilverLight程序之:获取SilverLight.Web项目中路径Uri
- 看到一个程序员成长之路 一点点感慨
- android scrollView 内部子布局MATCH_PARENT却无法填充满屏幕问题
- Codeforces Round #256 (Div. 2) B. Suffix Structures
- 程式師的使用介面設計手冊
- 如何输出源文件的标题和目前执行行的行数
- CORS实现跨域资源访问
- 李刚疯狂讲义目录