到目前为止,我们已经学习了两种创建新对象的方法:[类名 new] 和 [[类名 alloc] init]。这两种方法是等价的,不过Cocoa的惯例是使用后者。
有些语言(如C++和Java)使用构造函数在单次操作中执行对象的分配和初始化。Objective-C将这两种操作拆分为两个明确的步骤:分配和初始化。 分配(allocation):向某个类发送alloc消息的结果就是为该类分配一块足够大的内存,以存放该类的全部实例变量。同时,alloc方法还顺便将这块内存区域全部初始化为0。 初始化(initialization)从操作系统取得一块内存,准备用于存储对象。init方法几乎总是返回它们正在初始化的对象。应该像下面这样嵌套调用alloc和init方法:
Car *car = [[Car alloc] init];
而不是像下面这样:
Car *car = [Car alloc]; [car init];
这种嵌套调用技术非常重要,因为初始化方法返回的对象可能与分配的对象不同(见NSString章节末尾的类簇)。 编写初始化方法:
- (id) inti { if (self = [super init]) { // …. 进行初始化 )
return (set); }
便利初始化函数(convenience initializer),是用来完成某些额外工作的初始化方法,可以减少你自己完成这些工作的麻烦。例如:
// 返回一个空字符串 NSString *emptyString = [[NSString alloc] init];
// 按格式返回字符串 NSString *string = [[NSString alloc] initWithFormat:@"%d or %d", 25 124]; // 打开指定路径上的文本文件,读取文件内容 NSString *file = [[NSString alloc] initWithContentsOfFile: @"/tmp/words.txt"];
为了初始化的便利性,一个类可能有多个初始化方法。为了正确完成实例化并且子类继承时不出现问题,请明确一个“指定初始化函数”(designated initializer)。 类中的某个初始化方法被指派为指定初始化函数。该类的所有初始化方法使用指定初始化函数执行初始化操作。子类使用其超类的指定初始化函数实现超类的初始化。通常,接受参数最多的初始化方法最终成为指定初始化函数。 Example:
InitExample.h
1 // 2 // InitExample.h 3 // 示例类的初始化,添加指定初始化函数 4 // 5 // Created by Elf Sundae on 10/26/10. 6 // Copyright 2010 Elf.Sundae(at)Gmail.com . All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 12 @interface InitExample : NSObject 13 { 14 NSString *firstName; 15 NSString *lastName; 16 NSString *fullName; 17 } 18 19 - (void) setFirstName: (NSString *) firstName; 20 - (NSString *) firstName; 21 22 - (void) setLastName: (NSString *) lastName; 23 - (NSString *) lastName; 24 25 - (NSString *) fullName; 26 27 - (id) initWithFirstName: (NSString *) firstName; 28 - (id) initWithLastName: (NSString *) lastName; 29 - (id) initWithFirstName: (NSString *) firstName lastName:(NSString *) lastName; 30 31 @end
InitExample.m
1 // 2 // InitExample.m 3 // Initializer 4 // 5 // Created by Elf Sundae on 10/26/10. 6 // Copyright 2010 Elf.Sundae(at)Gmail.com . All rights reserved. 7 // 8 9 #import "InitExample.h" 10 11 12 @implementation InitExample 13 14 // ************************************************* 15 // 属性访问方法 16 - (void) setFirstName: (NSString *) m_firstName 17 { 18 firstName = m_firstName; 19 } 20 - (NSString *) firstName 21 { 22 return firstName; 23 } 24 25 - (void) setLastName: (NSString *) m_lastName 26 { 27 lastName = m_lastName; 28 } 29 - (NSString *) lastName 30 { 31 return lastName; 32 } 33 34 - (NSString *) fullName; 35 { 36 return [NSString stringWithFormat:@"%@ %@",firstName,lastName]; 37 } 38 39 // ************************************************* 40 // 初始化方法 41 42 // 指定初始化函数(designated initializer) 43 - (id) initWithFirstName: (NSString *) m_firstName 44 lastName:(NSString *) m_lastName 45 { 46 if (self = [super init]) 47 { 48 firstName = m_firstName; 49 lastName = m_lastName; 50 } 51 return self; 52 } 53 54 - (id) initWithFirstName: (NSString *) m_firstName 55 { 56 if (self = [self initWithFirstName:m_firstName 57 lastName:@"NoLastName"]){ 58 59 } 60 return self; 61 } 62 - (id) initWithLastName: (NSString *) m_lastName 63 { 64 if (self = [self initWithFirstName:@"NoFirstName" 65 lastName:m_lastName]){ 66 67 } 68 return self; 69 } 70 71 - (id) init 72 { 73 if (self = [self initWithFirstName:@"NoFirstName" 74 lastName:@"NoLastName"]){ 75 76 } 77 return self; 78 } 79 80 @end
SubClass.h
1 // 2 // SubClass.h 3 // 示例子类的初始化 4 // 5 // Created by Elf Sundae on 10/26/10. 6 // Copyright 2010 Elf.Sundae(at)Gmail.com . All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "InitExample.h" 11 12 @interface SubClass : InitExample 13 { 14 int age; 15 } 16 17 - (void) setAge : (int) age; 18 - (int) age; 19 20 - (id) initWithFirstName: (NSString *) m_firstName 21 lastName: (NSString *) m_lastName 22 age: (int) m_age; 23 24 - (id) initWithAge: (int) age; 25 26 27 @end
SubClass.m
1 // 2 // SubClass.m 3 // Initializer 4 // 5 // Created by Elf Sundae on 10/26/10. 6 // Copyright 2010 Elf.Sundae(at)Gmail.com . All rights reserved. 7 // 8 9 #import "SubClass.h" 10 11 12 @implementation SubClass 13 14 - (void) setAge:(int)m_age 15 { 16 age = m_age; 17 } 18 19 - (int) age 20 { 21 return age; 22 } 23 24 - (NSString *) description 25 { 26 return [NSString stringWithFormat:@"I am %@ ,and I'm %d years old.", 27 self.fullName,self.age]; 28 29 } 30 31 // 指定初始化函数 32 - (id) initWithFirstName: (NSString *) m_firstName 33 lastName: (NSString *) m_lastName 34 age: (int) m_age 35 { 36 if (self = [super initWithFirstName:m_firstName 37 lastName:m_lastName]) 38 { 39 age = m_age; 40 } 41 return self; 42 } 43 44 // 重写父类的指定初始化函数 45 - (id) initWithFirstName:(NSString *)m_firstName 46 lastName:(NSString *)m_lastName 47 { 48 // age 默认设为0 49 if (self = [self initWithFirstName:m_firstName 50 lastName:m_lastName 51 age:0]) 52 { 53 } 54 return self; 55 } 56 57 - (id) initWithAge:(int)m_age 58 { 59 if (self = [super init]) 60 { 61 age = m_age; 62 } 63 return self; 64 } 65 66 67 68 69 - (id) init 70 { 71 // age 默认设为0 72 if (self = [self initWithAge:0]) 73 { 74 } 75 return self; 76 } 77 78 @end 79
main
1 #import <Foundation/Foundation.h> 2 #import "InitExample.h" 3 #import "SubClass.h" 4 5 int main (int argc, const char * argv[]) { 6 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 7 8 InitExample *myName = [[InitExample alloc] init]; 9 NSLog(@"%@",[myName fullName]); 10 11 InitExample *myName1 = [[InitExample alloc] initWithFirstName:@"Elf"]; 12 NSLog(@"%@",[myName1 fullName]); 13 14 InitExample *myName2 = [[InitExample alloc] initWithLastName:@"Sundae"]; 15 NSLog(@"%@",[myName2 fullName]); 16 17 InitExample *myName3 = [[InitExample alloc] initWithFirstName:@"Elf" 18 lastName:@"Sundae"]; 19 NSLog(@"%@",[myName3 fullName]); 20 21 // 子类 22 SubClass *mySubClass = [[SubClass alloc] initWithAge:22]; 23 NSLog(@"%@",mySubClass); 24 25 SubClass *mySubClass1 = [[SubClass alloc] initWithFirstName:@"Elf"]; 26 NSLog(@"%@",mySubClass1); 27 28 SubClass *mySubClass2 = [[SubClass alloc] initWithFirstName:@"Elf" 29 lastName:@"Sundae"]; 30 NSLog(@"%@",mySubClass2); 31 32 SubClass *mySubClass3 = [[SubClass alloc] initWithFirstName:@"Elf" 33 lastName:@"Sundae" 34 age:22]; 35 NSLog(@"%@",mySubClass3); 36 37 SubClass *mySubClass4 = [[SubClass alloc] initWithLastName:@"Sundae"]; 38 NSLog(@"%@",mySubClass4); 39 40 [pool drain]; 41 return 0; 42 } 43 44
输出: NoFirstName NoLastName Elf NoLastName NoFirstName Sundae Elf Sundae I am NoFirstName NoLastName ,and I'm 22 years old. I am Elf NoLastName ,and I'm 0 years old. I am Elf Sundae ,and I'm 0 years old. I am Elf Sundae ,and I'm 22 years old. I am NoFirstName Sundae ,and I'm 0 years old.
总结: 在Cocoa中,分配和初始化是两个分离的操作:来自NSObject的类方法alloc为对象分配一块内存区域并将其清零,实例方法init用于获得一个对象并使其运行。 一个类可以拥有多个初始化方法。这些初始化方法通常是便利方法,可以更容易地实现你希望的对象配置方式。你可以从这些初始化方法中选择一个作为指定初始化函数。所有其他初始化方法应该按照指定初始化函数的形式编写。 在你自己的初始化方法中,需要调用自己的指定初始化函数或者超类的指定初始化函数。一定要将超类的初始化函数的值赋给self对象,并返回你自己的初始化方法的值。超类可能返回一个完全不同的对象。
文中代码下载:Download Initializer
|
请发表评论