目录

Objective-C_10.构造方法

一、构造方法

(一)构造方法的调用

完整的创建一个可用的对象:Person *p = [Person new];

new方法的内部会分别调用两个方法来完成2件事情。

  1. 使用alloc方法来分配存储空间(返回分配的对象);
  2. 使用init方法来对对象进行初始化。

可以把new方法拆开如下:

  1. 调用类方法+alloc分配存储空间,返回未经初始化的对象 : Person *p1=[person alloc];

  2. 调用对象方法-init进行初始化,返回对象本身 : Person *p2=[p1 init];

  3. 以上两个过程整合为一句:Person *p=[[Person alloc] init];

说明:init方法就是构造方法,是用来初始化对象的方法,注意这是一个对象方法,一减号开头。默认初始化完毕后,所有成员变量的值都为0。

(二)构造方法的代码示例

需求1,如果我需要让每个对象创建出来的初始值是10,而不是1,应该怎么办呢?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// Person 类的声明
@interface Person : NSObject

@property int age;

@end

/// Person类的实现
@implementation Person

// 重写init方法

- (instancetype)init
{
    // 1. 初始化对象拥有的父类成员变量
    self = [super init];
    if (self)
    {
        // 2. 初始化对象自有得成员变量
        _age = 10;
    }
    // 3. 返回一个已经初始化完成的对象
    return self;
}

@end

Person *p = [[Person alloc] init];
NSLog(@"%d", p.age);

// 打印结果
2016-07-30 00:31:46.785 test[28361:6773695] 10

需求2,让学生继承人类,要求学生对象初始化之后,年龄是10,学号是1,怎么办?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@interface Student : Person

@property int no;

@end

@implementation Student

- (instancetype)init
{
    // 1. 初始化对象拥有的父类成员变量, 调用父类的构造方法, 把年龄设置为10
    self = [super init];
    if (self)
    {
        // 2/初始化对象自有得成员变量, 设置no的值为1
        _no = 1;
    }
    // 3. 返回一个已经初始化完成的对象
    return self;
}

@end

Student *s = [[Student alloc] init];
NSLog(@"%d, %d", s.age, s.no);

// 打印结果
2016-07-30 00:37:22.160 test[28436:6799197] 10, 1

(三)构造方法使用注意

  1. 子类拥有的成员变量包括自己的成员变量以及从父类继承而来的成员变量,在重写构造方法的时候应该首先对从父类继承而来的成员变量先进行初始化。
  2. 原则:先初始化父类的,再初始化子类的。
  3. 重写构造方法的目的:为了让对象方法一创建出来,成员变量就会有一些固定的值。
  4. 注意点:#1先调用父类的构造方法[super init]; #2再进行子类内部成员变量的初始化。

二、自定义构造方法

(一)自定义构造方法的规范

  1. 一定是对象方法,以减号开头
  2. 返回值一般是id类型
  3. 方法名一般以initWith开头

(二)自定义构造方法的代码实

Person类的声明,其中声明了两个接收参数的自定义构造方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 // Person 类的声明
@interface Person : NSObject

@property NSString *name;
@property int no;

- (id)initWithName:(NSString *)name;

- (id)initWithName:(NSString *)name andNo:(int)no;

@end

Person类的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/// Person类的实现
@implementation Person
// 自定义构造方法

// 接受1个参数的构造方法
- (id)initWithName:(NSString *)name
{
    if (self = [super init])
    {
        _name = name;
    }
    return self;
}

// 接受2个参数的构造方法
- (id)initWithName:(NSString *)name andNo:(int)no
{
    if (self = [super init])
    {
        _name = name;
        _no = no;
    }
    return self;
}

@end

Student继承自Person类,声明了一个接收三个参数的构造方法

1
2
3
4
5
6
7
@interface Student : Person

@property int age;

- (id)initWithName:(NSString *)name andNo:(int)no andAge:(int)age;

@end

Student类的实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 学生类方法的实现
// 一个接受三个参数的自定义构造方法
@implementation Studen

- (id)initWithName:(NSString *)name andNo:(int)no andAge:(int)age
{
    if (self = [super initWithName:name andNo:no])
    {
        // 初始化自己独有的成员变量
        _age = age;
    }
    return self;
}

@end

测试主程序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 调用接受一个参数的自定义构造函数
Person *p = [[Person alloc] initWithName:@"xiaomi"];
NSLog(@"%@", p.name);

// 调用接受两个参数的自定义构造函数
Person *p2 = [[Person alloc] initWithName:@"xiaoming" andNo:1];
NSLog(@"%@ %d", p2.name, p2.no);

// 学生类调用接受三个参数的构造函数
Student *s = [[Student alloc] initWithName:@"xiaohong" andNo:3 andAge:4];
NSLog(@"%@,%d,%d", s.name, s.no, s.age);

// 打印结果
2016-07-30 00:52:40.865 test[28632:6861736] xiaomi
2016-07-30 00:52:40.866 test[28632:6861736] xiaoming 1
2016-07-30 00:52:40.866 test[28632:6861736] xiaohong,3,4

(三)自定义构造方法的使用注意

  1. 自己做自己的事情
  2. 父类的方法交给父类的方法来处理,子类的方法处理子类自己独有的属性