有时候仅仅靠重写构造方法(初始化方法),不能满足需求。比如一个班级中不可能所有学生的年龄都一样,这时候我们需要在创建某个学生的时候能够传入这个学生的年龄。这时候就需要来自定义构造函数(初始化函数)
自定义构造方法的规范
示例
@interface Person : NSObject
@property int age;
@property NSString *name;
// 当想让对象一创建就拥有一些指定的值,就可以使用自定义构造方法
- (id)initWithAge:(int)age;
- (id)initWithName:(NSString *)name;
- (id)initWithAge:(int)age andName:(NSString *)name;
@end
什么是工厂方法(快速创建方法)
自定义类工厂方法的规范
示例
+ (id)person;
+ (id)person
{
return [[Person alloc]init];
}
+ (id)personWithAge:(int)age;
+ (id)personWithAge:(int)age
{
Person *p = [[self alloc] init];
[p setAge:age];
return p;
}
其实苹果在书写工厂方法时也是按照这样的规划书写
[NSArray array];
[NSArray arrayWithArray:<#(NSArray *)#>];
[NSDictionary dictionary];
[NSDictionary dictionaryWithObject:<#(id)#> forKey:<#(id<NSCopying>)#>];
[NSSet set];
[NSSet setWithObject:<#(id)#>];
为了解决这个问题, 以后在自定义类工厂时候不要利用父类创建实例对象, 改为使用self创建, 因为self谁调用当前方法self就是谁
示例
@interface Person : NSObject
+ (id)person;
@end
@implementation Person
+ (id)person
{
return [[Person alloc]init];
}
@end
@interface Student : Person
@property NSString *name;
@end
@implementation Student
@end
int main(int argc, const char * argv[])
{
Student *stu = [Student person];// [[Person alloc] init]
[stu setName:@"lnj"]; // 报错, 因为Person中没有setName
}
@interface Person : NSObject
+ (id)person;
@end
@implementation Person
+ (id)person
{
// return [[Person alloc]init];
// 谁调用这个方法,self就代表谁
// 注意:以后写类方法创建初始化对象,写self不要直接写类名
return [[self alloc]init];
}
@end
@interface Student : Person
@property NSString *name;
@end
@implementation Student
@end
int main(int argc, const char * argv[])
{
Student *stu = [Student person];// [[Student alloc] init]
[stu setName:@"lnj"];
}
想在对象创建完毕后,成员变量马上就有一些默认的值就可以重写init方法
重写init方法格式:
- (id)init {
self = [super init];
if (self) {
// Initialize self.
}
return self;
}
+ [super init]的作用:
面向对象的体现,先利用父类的init方法为子类实例的父类部分属性初始化。 + self 为什么要赋值为[super init]: 简单来说是为了防止父类的初始化方法release掉了self指向的空间并重新alloc了一块空间。还有[super init]可能alloc失败,这时就不再执行if中的语句。
- (id)init {
if (self = [super init]) {
// Initialize self.
}
return self;
}
@implementation Person
- (instancetype)init
{
if (self = [super init]) {
_age = 10;
}
return self;
}
@end
@implementation Person
- (instancetype)init
{
if (self = [super init]) {
_age = 10;
}
return self;
}
@end
@implementation Student
- (instancetype)init
{
if (self = [super init]) {
_no = 1;
}
return self;
}
@end
千万不要把self = [super init]
写成self ==
[super init]
重写构造方法的目的:为了让对象方法一创建出来,成员变量就会有一些固定的值。
// init此时返回值是id
NSString *str = [[Person alloc] init];
// Person并没有length方法, 但是id是动态类型, 所以编译时不会报错
NSLog(@"length = %i", str.length);
// init此时返回值是instancetype
// 由于instancetype它会进行类型检查, 所以会报警告
NSString *str = [[Person alloc] init];
NSLog(@"length = %i", str.length);
instancetype *p = [[person alloc] init];
// 错误写法instancetype只能作为返回值
@interface Person : NSObject
@property int age;
- (id)initWithAge:(int)age;
@end
@interface Student : Person
@property NSString *name;
- (id)initWithAge:(int)age andName:(NSString *)name;
@end
@implementation Student
- (id)initWithAge:(int)age andName:(NSString *)name
{
if (self = [super init]) {
// 这个_Age是父类中通过property自动在.m中生成的无法继承,不能直接访问
// _age = age;
[self setAge:age];
_name = name;
}
return self;
}
@end
@interface Person : NSObject
@property int age;
- (id)initWithAge:(int)age;
@end
@interface Student : Person
@property NSString *name;
- (id)initWithAge:(int)age andName:(NSString *)name;
@end
@implementation Student
- (id)initWithAge:(int)age andName:(NSString *)name
{
if (self = [super initWithAge:age]) {
_name = name;
}
return self;
}
@end
(2)父类的属性交给父类的方法来处理,子类的方法处理子类自己独有的属性
自定义构造方法必须以intiWith开头,并且’W’必须大写
原文:http://www.cnblogs.com/zhoudaquan/p/5015790.html