前言:前段时间想为系统类extension
一些init
方法,编译器报错不能为该类添加指定指定构造器,并让我在init前添加convenience
,生成便利构造器。以此坑为契机,我对Swift的构造过程进行了一些了解。谨以此文记录我对Swift构造器的理解。
说明:本文提及的构造器为类构造器,不涉及值构造器。
作用:
为自身和继承来的存储属性赋初值。
构造器:
指定构造器:
类中必备的构造器,必须将类中的存储属性设置好值,必须至少有一个。有些子类可能不需要显示声明,默认继承基类的指定构造器。
其语法为 :
init(参数名:参数类型) {
// 构造器的实现
}
便利构造器:
辅助构造器,通过调用指定构造器为属性赋值,便利构造器不能和指定构造器方法同名、用 convenience 关键字声明。
其语法为:
convenience init(参数名:参数类型) {
// 构造器的实现
}
可失败构造器
一个类在构造过程中有可能失败,则为其定义一个可失败构造器。一个类可定义多个可失败构造器,其语法为:
init?(参数名:参数类型) {
// 构造器的实现
}
//-------参考代码:
class Person {
var name: String
var age: Int = 10
// MARK -- 指定构造器
init(name: String, age: Int) {
self.name = name
self.age = age
}
// MARK -- 便利构造器
convenience init() {
self.init(name: "jamalping", age: 11)
}
// MARK -- 可失败构造器
init?(age: Int) {
guard age > 0 else {
return nil
}
self.age = age
self.name = "jamalping"
}
}
print(Person.init(age: -1) ?? "Person 初始化失败") // 输出为:Person 初始化失败
必要构造器
在类的构造器前添加required修饰符表明所有该类的子类都必须实现该构造器:
其语法为:
required init(参数名:参数类型) {
// 构造器的实现
}
两段式构造过程
一、1.确保当前类和父类所有存储属性都被初始化。
二、做一些其它初始化操作。
好处: 1.可以防止属性在被初始化之前访问, 2.可以防止属性被另外一个构造器意外赋值
注意:构造器的初始化永远是在所有类的第一阶段初始化完毕之后才会开始第二阶段
如下:
//-------参考代码:
class Man: Person {
var weight: Int
init(weight: Int) {
print("初始化第一阶段开始")
self.weight = weight
// 对父类的属性进行初始化
super.init(name: "jamalping", age: 33)
print("初始化第二阶段开始")
if self.age > 30 {
self.name = "jamal"
}
}
}
Man.init(weight: 100).name // 输出结果为jamal```
##构造器链(指定构造器与便利构造器间的调用关系)
######规则:
1、指定构造器必须调用父类的指定构造器。
2、便利构造器必须调用同一类中其他的构造器。
3、便利构造器必须以调用一个指定构造器结束。
**总结**:指定构造器是向上调用的,便利构造器是横向调用的。
//-------参考代码:
class Person1 : Person {
var age: Int
var weight: Int = 100
init(age: Int) {
// 先初始化存储属性、再调用父类的指定构造器
self.age = age
super.init(name: "jamalping")
}
convenience init(age: Int, weight: Int) {
// 先调用指定构造器初始化self、再初始化其他属性
self.init(weight: weight)
self.age = age
}
convenience init(weight: Int) {
self.init(age: 22, weight: weight)
}
}
构造器的继承
Swift的子类不会默认继承父类的构造器,满足以下条件之一会自动继承
1、子类没有定义指定构造器
2、子类实现了父类的所有指定构造器
如下:两种情况都满足条件,所以子类自动继承了父类的构造器
//-------参考代码:
class Man: Person {
// 没有定义指定构造器
}
class Women: Person {
//实现了父类的所有指定构造器
override init(name: String) {
super.init(name: name)
}
}
Man.init().name // name为"jamalping"
Women().name // name为"jamalping"
构造器的重写
其语法为:
override init(参数名:参数类型) {
// 构造器的实现
}
class Man1: Person {
// 指定构造器的重写
// 如果子类中的构造器和父类一模一样, 必须加上override关键字, 表示重写父类方法
// override init(name: String, age: Int) {
// super.init(name: name, age: age)
// self.name = "super man"
// }
// 将父类的指定构造器重写成一个便利构造器, 也必须加上override关键字, 表示重写父类方法
override convenience init(name: String, age: Int) {
self.init(name: name, age: age)
}
// 将父类的可失败构造器重写成指定构造器
// override init(age: Int) {
// super.init(name: "jamalping", age: age)
// }
// 将父类的可失败构造器重写成便利构造器
override convenience init(age: Int) {
self.init(name: "jamalping", age: age)
}
}
注意:
便利构造器不存在重写
extension一个类的构造器,只能extension便利构造器