iOS self 和 super区别以及为什么要self = [super init];

 

 联系人:石虎 QQ:1224614774  昵称: 嗡嘛呢叭咪哄

                        QQ群:807236138  群称: iOS 技术交流学习群

 

 

一、selfsuper区别

区别:

- self调用自己方法,super调用父类方法

- self是类,super是预编译指令

- self class】和【super class】输出是一样的

self和super底层实现原理:

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

 

- 当使用 self 调用时,会使用 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 调用时,会使用 objc_msgSendSuper 函数:id objc_msgSendSuper(struct objc_super *super, SEL op, ...)第一个参数是个objc_super的结构体,第二个参数还是类似上面的类方法的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 



@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 的超类开始 寻找。

 

 

谢谢!!!

你可能感兴趣的:(iOS,知识点)