swift init构造方法,convinience 及 convinience, swift和OC的初始化思路对比

在学习如何使用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

最后来一张图,看下两种初始化函数之间的区别:

image.png

Guess you like

Origin juejin.im/post/7034486519641407525