技术开发 频道

Objective-C边学边记:对象初始化

  【IT168技术】到目前为止,我们已经学习了两种创建新对象的方法:[类名 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 }

       总结:
        在Cocoa中,分配和初始化是两个分离的操作:来自NSObject的类方法alloc为对象分配一块内存区域并将其清零,实例方法init用于获得一个对象并使其运行。
        一个类可以拥有多个初始化方法。这些初始化方法通常是便利方法,可以更容易地实现你希望的对象配置方式。你可以从这些初始化方法中选择一个作为指定初始化函数。所有其他初始化方法应该按照指定初始化函数的形式编写。
        在你自己的初始化方法中,需要调用自己的指定初始化函数或者超类的指定初始化函数。一定要将超类的初始化函数的值赋给self对象,并返回你自己的初始化方法的值。超类可能返回一个完全不同的对象。

0
相关文章