黑马程序员-构造方法
一、构造方法的作用
用来初始化对象的成员变量值,当我们在创建对象时,需要一些成员变量具有一定的初始值,这个时候就要用到构造方法。利用类的new方法可以创建一个对象,这个new方法其实是分两步来完成创建对象的。
1> 调用+alloc来分配存储空间 Person *p1 = [Person alloc];
2> 调用-init进行初始化,Person *p2 = [p1 init];
这样我们就可以重写-init方法进行一些成员变量的初始化了。看下面实例
1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObject 4 @property int age; 5 @end
1 #import "Person.h" 2 3 @implementation Person 4 5 - (id)init 6 { 7 if ( self = [super init] ) 8 { // 初始化成功 9 _age = 10; 10 } 11 12 // 3.返回一个已经初始化完毕的对象 13 return self; 14 } 15 16 @end
1 #import "Person.h" 2 3 @interface Student : Person 4 @property int no; 5 @end
1 #import "Student.h" 2 3 @implementation Student 4 5 // 学生对象初始化完毕后,年龄就是10,学号就是1 6 7 - (id)init 8 { 9 if ( self = [super init] ) 10 { 11 _no = 1; 12 } 13 return self; 14 } 15 16 @end
需要注意的是:一定要调用super的init方法来初始化父类中声明的一些成员变量和其他属性,在进行子类内部成员变量的初始化。
二、自定义构造方法
有时我们需要在创建某个对象的同时给对象一个和其他对象不同的成员变量初始值,此时需要自定义构造方法。
自定义构造方法的规范
1> 一定是对象方法,一定以 - 开头
2> 返回值一般是id类型
3> 方法名一般以initWith开头
看下面的实例:
1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObject 4 @property NSString *name; 5 @property int age; 6 7 - (id)initWithName:(NSString *)name; 8 9 - (id)initWithAge:(int)age; 10 11 - (id)initWithName:(NSString *)name andAge:(int)age; 12 13 @end
1 #import "Person.h" 2 3 @implementation Person 4 5 - (id)init 6 { 7 if ( self = [super init] ) 8 { 9 _name = @"Jack"; 10 } 11 return self; 12 } 13 14 - (id)initWithName:(NSString *)name andAge:(int)age 15 { 16 if ( self = [super init] ) 17 { 18 _name = name; 19 _age = age; 20 } 21 return self; 22 } 23 24 @end
1 #import "Person.h" 2 3 @interface Student : Person 4 @property int no; 5 6 - (id)initWithNo:(int)no; 7 8 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no; 9 10 @end
#import "Student.h" @implementation Student - (id)initWithNo:(int)no { if ( self = [super init] ) { _no = no; } return self; } // 父类的属性交给父类方法去处理,子类方法处理子类自己的属性 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no { // 将name、age传递到父类方法中进行初始化 if ( self = [super initWithName:name andAge:age]) { _no = no; } return self; } @end
自定义子类构造方法的时候,如果需要重新初始化父类传下来的一些成员变量,应该首先看父类中有没有这些成员变量的构造函数,如果有的话就调用父类的构造函数。也就是说我们应该遵循这种原则:父类的属性应该交给父类方法去处理,子类方法处理子类自己的属性。上面student子类构造方法的实现如果如下这样写的话会显得很不专业。
1 #import "Student.h" 2 3 @implementation Student 4 - (id)initWithNo:(int)no 5 { 6 if ( self = [super init] ) 7 { 8 _no = no; 9 } 10 return self; 11 } 12 13 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no 14 { 15 if ( self = [super init] ) 16 { 17 _no = no; 18 self.name = name; 19 self.age = age; 20 //[self setName:name]; 21 //[self setAge:age]; 22 } 23 24 return self; 25 } 26 @end
这样写的缺点在于
1> 父类的属性应该交给父类方法去处理,子类方法处理子类自己的属性
2> 如果此时修改父类的成员变量名称,就需要修改对象的子类的构造方法,会造成一定的麻烦。