一、构造方法的作用:
构造方法是用来初始化对象的方法,是个对象方法,-开头。构造方法只有一个作用,就是初始化成员变量。当一个对象初始化的时候需要有默认值,就可以用到构造方法。
二、构造方法的原则:
成员变量属于哪个类,就在哪个类那里进行初始化。父类的属性交给父类方法去处理,子类方法处理子类自己的属性。
三、构造方法的应用场景:
3.1 new方法的调用
new方法是一个类方法,它是alloc类方法和init对象方法的连合体,相当于new方法内部调用了alloc方法和init方法。因此当有重写init方法时,调用new方法时,它内部就会调用init方法进行初始化。一般使用类似于:Person *p=[Person new];完整地创建一个对象会有以下两个步骤:
1>分配存储空间(new方法内部调用+alloc)
`2>初始化 (new方法内部调用-init)
3.2 重写-init方法
1>init是一个对象方法,可以通过类似于:Person *p=[[Person alloc] init];来显式地调用init方法进行初始化。
2>重写init方法,在方法内部开头一定要调用回super的init方法,来对父类中声明的一些变量和属性进行初始化。调用super的init方法成功后,才有必要进行接下来的初始化。初始化成功后返回一个已经初始化完毕的对象。
3>子类重写父类的init方法,只需要初始化自己声明的成员变量。父类的成员变量可以由父类自己进行初始化。这样可以避免当父类成员变量名有所改动时,而导致的连环改动。
3.3 自定义构造方法
1>当需要通过外部传递参数给构造方法进行指定成员变量的初始化时,就需要用到自定义构造方法。这种初始化方式比较灵活。
2>自定义构造方法的规范:一定是对象方法,一定以-开头;返回值一般是id类型;方法名一般以initWith开头。
3>当需要初始化父类的成员变量时,尽量使用父类提供的构造方法进行初始化父类的成员变量。
#import <Foundation/Foundation.h>
@interface Person :NSObject
@property int age;
@property NSString *name;
//返回值是id类型
-(id)initWithAge:(int)age;
-(id)initWithName:(NSString *)name;
-(id)initWithAge:(int)age andName : (NSString *)name;
@end
@implementation Person
//重写init方法,在方法内部开头一定要调用回super的init方法,来对父类中声明的一些变量和属性进行初始化。调用super的init方法成功后,才有必要进行接下来的初始化。初始化成功后返回一个已经初始化完毕的对象。
- (id)init
{
//如果父类对象初始化成功,就进行接下来的成员变量的初始化
if (self = [super init]){
_age = 20;
}
//返回一个已经初始化完毕的对象
return self;
}
/*这种方式比较繁琐,一般采用上面那种方式重写构造方法
-(id)init
{
//调用super的init方法:初始化父类中声明的一些成员变量和其他属性并返回给self
self=[super init];
//如果对象初始化成功,才有必要进行接下来的初始化
if(self!=nil)
{
//初始化成功后初始化成员变量
_age=20;
}
//返回一个已经初始化完毕的对象
return self;
}
*/
/*
自定义构造方法的实现
自定义构造方法的规范:
1.一定是对象方法,一定以-开头;
2.返回值一般是id类型;
3.方法名一般以initWith开头。
*/
-(id)initWithAge:(int)age
{
if (self = [super init])
{
_age = age;
}
return self;
}
-(id)initWithName:(NSString *)name
{
if (self = [super init])
{
_name = name;
}
return self;
}
-(id)initWithAge:(int)age andName : (NSString *)name
{
if (self = [super init])
{
_age = age;
_name = name;
}
return self;
}
@end
@interface Student : Person
@property int no;
-(id)initWithName:(NSString *)name andAge : (int)age andNo : (int)no;
@end
@implementation Student
//注释与Person重写init方法一样,Person重写了NSObject的init方法
- (id)init
{
if (self = [super init])
{
_no = 1;
}
return self;
}
// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性
-(id)initWithName:(NSString *)name andAge : (int)age andNo : (int)no
{
// 将name、age传递到父类方法中进行初始化
if (self = [super initWithAge : age andName : name])
{
_no = no;
}
return self;
}
/* 这种采用self来初始化父类成员变量的方式比较少用
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
if ( self = [super init] )
{
_no = no;
//_name = name;
self.name = name;//点语法
self.age = age;
//[self setName:name];//self调用:默认先查找当前子类的方法,如果找不到再到父类方法中查找
//[self setAge:age];
}
return self;
}
*/
@end
int main()
{
/*
new方法是一个类方法,它是alloc类方法和init对象方法的连合体,相当于new方法内部调用了alloc方法和init方法。调用new方法时,它内部就会调用init方法进行初始化。完整地创建一个对象会有以下两个步骤:
1>分配存储空间(new方法内部调用+alloc)
2>初始化 (new方法内部调用-init)
*/
Person *p1 = [Person new];
NSLog(@"通过new方法获得这个人%d岁了", p1.age);
Person *p2 = [[Person alloc]init];
NSLog(@"通过init方法获得这个人%d岁了", p2.age);
Student *s1 = [[Student alloc]init];
NSLog(@"子类对象Student重写init方法之后,学号是%d,年龄是%d", s1.no, s1.age);
Person *p3 = [[Person alloc]initWithAge:11];
NSLog(@"通过自定义构造方法initWithAge方法获得这个人%d岁了", p3.age);
Person *p4 = [[Person alloc]initWithName:@"Jack"];
NSLog(@"通过自定义构造方法initWithName方法获得这个人%d岁了,名字是%@", p4.age, p4.name);
Person *p5 = [[Person alloc]initWithAge:12 andName : @"Tom"];
NSLog(@"通过自定义构造方法initWithAgeandName方法获得这个人%d岁了,名字是%@", p5.age, p5.name);
Student *s2 = [[Student alloc]initWithName:@"Jim" andAge:15 andNo : 2];
NSLog(@"子类对象Student重写initWithAgeandNameandNo方法之后,学号是%d,年龄是%d,名字是%@", s2.no, s2.age, s2.name);
return 0;
}
输出结果:
2015-02-07 09:41:51.878 a.out[534:13741] 通过new方法获得这个人20岁了
2015-02-07 09:41:51.880 a.out[534:13741] 通过init方法获得这个人20岁了
2015-02-07 09:41:51.880 a.out[534:13741] 子类对象Student重写init方法之后,学号是1,年龄是20
2015-02-07 09:41:51.880 a.out[534:13741] 通过自定义构造方法initWithAge方法获得这个人11岁了
2015-02-07 09:41:51.881 a.out[534:13741] 通过自定义构造方法initWithName方法获得这个人0岁了,名字是Jack
2015-02-07 09:41:51.881 a.out[534:13741] 通过自定义构造方法initWithAgeandName方法获得这个人12岁了,名字是Tom
2015-02-07 09:41:51.881 a.out[534:13741] 子类对象Student重写initWithAgeandNameandNo方法之后,学号是2,年龄是15,名字是Jim