在学习如何使用swift的init构造方法的具体用法前,我们先设想一个场景: 有个学生系统包含学生类,学生有名字和年龄,名字是必填的,年龄是非必填的,如何设计这个类呢?
OC是如何完成的?
我们先使用OC来完成,方便后面对比:
先看下类设计:
@interface LFStudent : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end
然后我们增加下初始化方法,这里我们要使用OC中特有的全能方法,然后为了方便用户只需要初始化名称的场景,我们会增加一个只包含name入参的函数,函数如下:
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
? ? if (self = [super init]) {
? ? ? ? _name = name;
? ? ? ? _age = age;
? ? }
? ? return self;
}
- (instancetype)initWithName:(NSString *)name
{
? ? return [self initWithName:name age:-1];
}
这里注意,我们只使用了一个可以最终初始化的全能方法,而其他的方法,我们是调用这个全能方法来完成的,有了全能方法,能保证我们的类的初始化的最后都是收到一个入口
Swift 如何完成初始化
那么如果使用swift要如何写呢? swift中的init方法分为两种,指定构造designated init和方便构造 convenience init
我们的第一反应可能是想和OC一样,定一个类似全能方法,然后其他的初始化方法调用这个全能方法即可,但是很遗憾,swif中designated方法不能调用其他的designated方法,只能调用super.init,也就是说,以下的初始化是会报错的:
init(name: String?, age : Int){
super.init()
self.name = name
self.age = age
}
init(name: String?){
init(name: name, age : -1) //error
}
convinience 和 designated
那如果我们要如何实现呢? 肯定是不希望重复定义多个重复设置属性的函数,这样收口有多个,很容易出现后期不一致的问题,这里就要使用 convinience init了,swift规定,convenience 是可以调用指定构造 designated init的,所以我们通常会将designated做成全能方法(本来也是如此设定的),然后使用 convenience 来做修饰,提供方便快捷的构造方法,具体实现如下:
init(name: String?, age : Int){
super.init()
self.name = name
self.age = age
}
convenience init(name: Stirng?){
self.init(name: name, age: -1)
}
完成,convenience方法完美的解决了快速初始化的需求
注意事项
- swift的init定义不需要使用func修饰
- swift 初始化中 designated 为主初始化, 需要的话使用 convinience 来补充 ,convinience 可以调用designated, designated只能调用super
- swift的init不需要return
最后来一张图,看下两种初始化函数之间的区别:
|