在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
7,对象的初始化以及实例变量的作用域本系列讲座有着很强的前后相关性,如果你是第一次阅读本篇文章,为了更好的理解本章内容,笔者建议你最好从本系列讲座的第1章开始阅读,请点击这里。 到目前为止,我们都使用的是下列方式创建对象
[类名 new];
这种new的方式,实际上是一种简化的方式。笔者在这里总结一下前面几章里面曾经提到过关于创建对象的2个步骤: 第一步是为对象分配内存也就是我们所说的allocation,runtime会根据我们创建的类的信息来决定为对象分配多少内存。类的信息都保存在Class里面,runtime读取Class的信息,知道了各个实例变量的类型,大小,以及他们的在内存里面的位置偏移,就会很容易的计算出需要的内存的大小。分配内存完成之后,实际上对象里面的isa也就被初始化了,isa指向这个类的Class。类里面的各个实例变量,包括他们的超类里面的实例变量的值都设定为零。 需要注意的是,分配内存的时候,不需要给方法分配内存的,在程序模块整体执行的时候方法部分就作为代码段的内容被放到了内存当中。对象的内容被放到了数据段当中,编译好的方法的汇编代码被放到了代码段当中。在Objective C里面,分配内存使用下列格式: id 对象名=[类名 alloc];
NSObject已经为我们提供了诸如计算内存空间大小以及初始化isa还有把各个实例变量清零,毫无疑问NSObject已经非常出色的完成了内存分配的工作,在一般情况下,我们不需要重写alloc方法。 第二步是要对内存进行初始化也就是我们所说的Initialization。 初始化指的是对实例变量的初始化。虽然在alloc方法里面已经把各个实例变量给清零了,但是在很多情况下,我们的实例变量不能是零(对于指针的实例变量而言,就是空指针)的,这样就需要我们对实例变量进行有意义的初始化。 按照Objective-C的约定,当初始化的时候不需要参数的话,就直接使用init方法来初始化:
[对象名字 init];
init是一个定义在NSObject里面的一个方法,NSObject明显无法预测到派生类的实例变量是什么,所以同学们在自己的类里面需要重载一下init方法,在init方法里面把实例变量进行初始化。 但是,需要强调的是,由于某种原因我们的init也许失败了,比如说我们需要读取CNBLOGS.COM的某个RSS,用这个RSS来初始化我们的对象,但是由于用户的网络连接失败所以我们的init也许会失败,在手机应用当中的一些极端的情况下比如说有同学写一个读取网页内容的程序,在网页内容非常大的时候,那么alloc也有可能会失败,为了可以方便的捕获这些失败,所以我们在程序当中需要把上面的过程写在一起:
id 对象名 = [[类名 alloc] init];
if (对象名) else 加上了上面的if语句我们的初始化过程就是完美的,当然我们有的时候不需要这个if语句。当我们的alloc和init永远不会失败的时候。关于初始化的时候的错误捕获,笔者将在后面的章节里面论述。 为了我们写程序方便和简洁,在创建一个从NSObject派生的类的对象的时候,苹果公司把alloc和init简化成为new,我们在程序代码当中使用任何一种方式都是可以的,具体怎么写是同学们的喜好和自由。 到这里,有同学会问,如果我们的init需要参数怎么办?按照Objective-C的约定,我们需要使用initWith...。也就是带参数的变量初始化,这个也是本章的主要内容。 本章在讲述initWith的同时,也将会顺便的给大家介绍一下实例变量的作用域。
7.1,本章程序的执行结果在本章里面,我们将要继续使用我们在第4章已经构筑好的类Cattle和Bull。从一般的面向对象的角度上来说,是不鼓励我们改写已经生效的代码的。但是本章的目的是为了使同学们可以很好的理解主题,所以笔者在这里暂时违反一下规则改写了一下Cattle类,在里面追加了initWith方法,笔者也在Cattle类里面追加了一些实例变量为了阐述实例变量的作用域的问题。由于在Cattle类里面笔者追加了一些东西,所以在Bull类里面改写了saySomething这个函数,让我们的Bull可以说更多的内容。我们的redBull是这样说的:
图7-1,本章程序的执行结果 本章程序代码晴点击这里下载。 7.2,实现步骤第一步,按照我们在第2章所述的方法,新建一个项目,项目的名字叫做07-InitWithAndIvarScope。如果你是第一次看本篇文章,请到这里参看第二章的内容。 第二步,按照我们在第4章的4.2节的第二,三,四步所述的方法,把在第4章已经使用过的“Cattle.h”,“Cattle.m”,“Bull.h”还有“Bull.m”, 导入本章的项目里面。然后把第6章里面的“MyNSObject.h”也导入到项目当中。 第三步,打开“Cattle.h”,修改成为下面的代码并且保存:
#import <Foundation/Foundation.h>
@interface Cattle : NSObject { int legsCount; @private bool gender; //male = YES female = NO @protected int eyesCount; @public NSString *masterName; } - (void)saySomething; - (void)setLegsCount:(int) count; - (id)initWithLegsCount:(int) theLegsCount gender:(bool) theGender eyesCount:(int) theEyesCount masterName:(NSString*)theMasterName; @end 第4步,打开“Cattle.m”,修改成下面的代码并且保存:
#import "Cattle.h"
@implementation Cattle -(void) saySomething { NSLog(@"Hello, I am a cattle, I have %d legs.", legsCount); } -(void) setLegsCount:(int) count { legsCount = count; } -(id)init { [super init]; return [self initWithLegsCount:4 gender:YES eyesCount:2 masterName:@"somebody"]; } - (id)initWithLegsCount:(int) theLegsCount gender:(bool) theGender eyesCount:(int) theEyesCount masterName:(NSString*)theMasterName { legsCount = theLegsCount; gender = theGender; eyesCount = theEyesCount; masterName = theMasterName; return self; } @end 第五步,打开“Bull.m”, ,修改成下面的代码并且保存:
#import "Bull.h"
@implementation Bull -(void) saySomething { NSLog(@"Hello, I am a %@ bull, I have %d legs.", [self getSkinColor],legsCount); NSLog(@"I have %d eyes, my master is %@.", eyesCount,masterName); //List below is illegal //NSLog(@"My gender is %@",gender ? @"male" : @"female"); } -(NSString*) getSkinColor { return skinColor; } - (void) setSkinColor:(NSString *) color { skinColor = color; } @end 第六步,打开“07-InitWithAndIvarScope.m”,修改成下面的代码并且保存:
#import <Foundation/Foundation.h>
#import "Bull.h" #import "Cattle.h" #import "MyNSObject.h" int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Bull *redBull = [[Bull alloc] initWithLegsCount:4 gender:YES eyesCount:2 masterName:@"that cowboy"]; [redBull setSkinColor:@"red"]; [redBull saySomething]; //legal, but not good redBull->masterName = @"that cowgirl"; //legal, but bad //redBull->eyesCount = 3; //Trying to access a private ivar, VERY bad thing //MyClass bullClass = redBull->isa; bool *redBullGender = (bool *)(redBull) + 8; NSLog(@"My gender is %@",*redBullGender ? @"male" : @"female"); [pool drain]; return 0; } 第七步,选择屏幕上方菜单里面的“Run”,然后选择“Console”,打开了Console对话框之后,选择对话框上部中央的“Build and Go”,如果不出什么意外的话,那么应该出现入图7-1所示的结果。如果出现了什么意外导致错误的话,那么请仔细检查一下你的代码。如果经过仔细检查发现 还是不能执行的话,可以到这里下载笔者为同学们准备的代码。 如果笔者的代码还是不能执行的话,请告知笔者。 7.3,实例变量的作用域(Scope)
|
请发表评论