最近学习Objective-C,鉴于所有语言入门级讲解,对一些语法点讲解不够透彻,因此觉得有必要对一些语法点进行记录。
假如有两个类A,B,A继承于B,即A是B的派生类,对A进行初始化如下:
A *a = [[A alloc] init];
这行代码的含义是,类A产生一个对象,为对象分配内存(alloc),然后在调用 初始化方法。这是a指针的内存状态如下
self = [super init]
最初我对这句话的理解是,将对象本省sefl的指针指向了父类对象的地址 即b,然后产生了很多疑惑,比如,这样一来,那self还怎么访问自身对象属性!??但其实不然。
1、先理解self,先看看init方法的配对使用,也就是oc的惯用方法,[A alloc]init,其实,在任意一个对象方法里打印self,我们都会得到一个相同的地址,也就是说alloc在分配给一个子类内存的时候,self已经出现,runtime在发送消息的时候,self是隐含参数之一,self是子类接收消息的入口,咱们在写下面这样的init方法时看似调用了[super init],也就是父类的方法,
-(instantType)init{
self = [super init];
if(self){
//初始化
}
return self;
}
但是我们还是在子类里调用的,目前alloc在内存里也完全是按照子类需要的内存大小分配的内存空间,既然在消息机制里,需要消息的接收主体,或者说入口,同时内存里又是为子类分配的内存,所以说在子类里调用任何方法,包括用super调用父类的方法,消息的接收实体都是当前子类,super只是告诉编译器查找方法的时候再父类方法列表里 去查找.根本不可能越过这个子类把消息直接发送到父类里去.趁热打铁看下面的代码
for B(父类 父类)
-(instantType)init{
self = [super init];
if(self){
//初始化
}
return self;
}
for A(子类 子类)
-(instantType)init{
self = [super init];
if(self){
//初始化
}
return self;
}
执行上面代码,将断点打在父类和子类的self中,会发现,父类的self和子类的self是一样的,也就是说[super init]的执行主体依然是子类,self直接赋值不会发生变化,只是if的条件判断。
这样做的意义在于,我们想要用到子类的实例,比如我们想实例一个button,那么我们必将用到button继承于uiview的某些属性,如果由于某些原因[super init]在初始化他的属性时没有成功,在父类的init方法里返回了一个nil,那么我们得到的button实例的self 也就是这个实例将会同样是nil,不会傻傻的用一个残疾的self去做事情.当然还有其他情况,比如类簇等等,苹果前面的链接里说的很清楚.当然有时候我们写成了self == [super init]也是ok的,这样写的风险就是排除不了父类返回nil的情况,因为self 与[super init]的结果本来正常情况下就应该是相等的!