- 在OC中init开头的方法, 我们称之为构造方法
构造方法的用途: 用于初始化一个对象, 让某个对象一创建出来就拥有某些属性和值
1.重写init方法
想在对象创建完毕后,成员变量马上就有一些默认的值就可以重写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中的语句。
// 重写init方法, 在init方法中初始化成员变量
// 注意: 重写init方法必须按照苹果规定的格式重写, 如果不按照规定会引发一些未知的错误
// 1.必须先初始化父类, 再初始化子类
// 2.必须判断父类是否初始化成功, 只有父类初始化成功才能继续初始化子类
// 3.返回当前对象的地址
- (instancetype )init
{ // 1.初始化父类
// 只要父类初始化成功 , 就会返回对应的地址, 如果初始化失败, 就会返回nil
// nil == 0 == 假 == 没有初始化成功
self = [super init];
// 2.判断父类是否初始化成功
if (self != nil) {
// 3.初始化子类
// 设置属性的值
_age = 6;
}
// 4.返回地址
return self;
}
2.练习
- 要求通过Person类创建出来的人初始化值都是10岁。
@implementation Person
- (instancetype)init
{
if (self = [super init]) {
_age = 10;
}
return self;
}
@end
3.构造方法使用注意
-
子类拥有的成员变量包括自己的成员变量以及从父类继承而来的成员变量,在重写构造方法的时候应该首先对从父类继承而来的成员变量先进行初始化。
-
原则:先初始化父类的,再初始化子类的。
先调用父类的构造方法[super init];
再进行子类内部成员变量的初始化。
千万不要把self = [super init]写成self == [super init] -
重写构造方法的目的:为了让对象方法一创建出来,成员变量就会有一些固定的值。
4.instancetype的作用
- instancetype与id相似,不过instancetype只能作为方法返回值,它会进行类型检查,如果创建出来的对象,赋值了不相干的对象就会有一个警告信息,防止出错。
// 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只能作为返回值
自定义构造方法
1.自定义构造方法
- 有时候仅仅靠重写构造方法(初始化方法),不能满足需求。比如一个班级中不可能所有学生的年龄都一样,这时候我们需要在创建某个学生的时候能够传入这个学生的年龄。这时候就需要来自定义构造函数(初始化函数)
自定义构造方法的规范
(1)一定是对象方法,以减号开头
(2)返回值一般是instancetype类型
(3)方法名必须以initWith开头
- 示例
@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
继承中的自定义构造方法
- 不能在子类访问父类私有变量
@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
initsuper.png
2.自定义构造方法的使用注意
-
(1)自己做自己的事情
-
(2)父类的属性交给父类的方法来处理,子类的方法处理子类自己独有的属性
-
自定义构造方法必须以intiWith开头,并且’W’必须大写
网友评论