《iOS应用程序开发方法与实践》答疑-关于对象创建、self、成员变量与属性

来源:互联网 发布:单片机触摸屏控制 编辑:程序博客网 时间:2024/05/17 04:23

转载自:http://blog.csdn.net/pucker/article/details/32129387


有很多读者跟我说,他们在self、访问类的成员变量(variable)以及调用类的属性(property)时遇到了问题,因此我打算在此详细解释一下。

一、对象的内存分配与初始化

我们首先要定义类,然后才能创建类的对象并使用它们。但是对象在创建和使用之前,要经过内存分配(Memory Allocation)与初始化(Initialization)两个过程。内存分配是指应用程序向操作系统申请一段内存空间,用来保存对象的所有成员变量的值。而初始化则是指对象在使用之前将其成员变量的值置为正确的初始值。

为了说明上述两个过程的作用,我们先看一下下面的例子:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @interface BaseClass : NSObject  
  2. {  
  3.     int _baseIntVar;  
  4. }  
  5. @end  
  6.   
  7. @interface SubClass : BaseClass  
  8. {  
  9.     int _subIntVar;  
  10. }  
  11. @end  

这里定义了BaseClass和SubClass两个类,其中BaseClass继承自NSObject类,而SubClass继承自BaseClass类。当需要创建SubClass类的对象时,我们一般都会这么写:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. SubClass* newSub = [[SubClass alloc] init];  

这里以串接的方式,连续调用了alloc与init方法。其中alloc方法是NSObject类中定义的一个静态方法:

[objc] view plaincopy
  1. @interface NSObject <nsobject>  
  2. {  
  3.     Class isa;  
  4. }  
  5. + (id)alloc;  
  6. ...  
  7. @end  

alloc方法用于实现对象的内存分配,它能够计算出对象需要的内存空间大小,然后向操作系统申请内存并将得到的内存空间全部清零,最后返回内存空间的首地址。对于上面的例子,当为SubClass对象分配内存时,由于类的继承关系,alloc方法会向操作系统申请一块包含isa、_baseIntVar与_subIntVar的内存空间,其中isa指向SubClass类对象,其余成员变量均为0,最后返回内存空间的首地址。内存清零的意思是指,对于类的成员变量,int类型为0,float、double为0.0,BOOL类型为NO,对象指针为nil。

init是默认的初始化方法,我们也可以自己定义初始化方法为成员变量赋初值,例如:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @implementation SubClass  
  2. - (id)init  
  3. {  
  4.     self = [super init];  
  5.     if (self)  
  6.     {  
  7.         _subIntVar = 1;  
  8.     }  
  9.     return self;  
  10. }  
  11. @end  

这里定义了子类SubClass的初始化方法init。其中第一句:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. self = [super init];  
这是一种Objective-C中约定俗成的写法,在init中调用当前类的基类的初始化方法(即BaseClass的init方法,其中的super关键字用于调用基类中的方法),并赋值给self(self关键字表示接收当前消息的对象引用)。这条语句的目的是在初始化子类(SubClass)对象时,首先调用基类(BaseClass)的初始化方法,将基类中定义的成员变量先初始化好,然后再将子类中定义的成员变量初始化。

你可能觉得奇怪,为什么要将基类初始化方法的返回值赋值给self?这是因为基类的初始化方法有可能会返回另外一个对象的地址,而不是当初调用init方法的对象地址。所以我们在创建对象的时候,不应该把alloc语句与init语句分开,必须串接起来。

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. SubClass* newSub = [[SubClass alloc] init]; //正确  
  2.   
  3. //SubClass* newSub = [SubClass alloc];   
  4. //[newSub init]; //错误,init方法有可能返回另一个地址  


二、关于self


未完待续。。。


0 0
原创粉丝点击