本篇继续对Swift中的构造器进行介绍,这里主要说到类的继承和构造。 作为引用类型的类具有的继承特性,这使得类的构造过程较为复杂一些,因为涉及到很多细节性的问题。在使用之前,我们需要了解一些基本的问题:
class FatherClass {
var valueOne: Int
//指定构造器
init(valueOne: Int){
self.valueOne = valueOne
}
}
class ChildClass: FatherClass {
var valueTwo:Int //子类的新引入属性
//指定构造器
init(valueOne: Int , valueTwo:Int){
self.valueTwo = valueTwo
//先初始化新引入属性,再初始化超类
super.init(valueOne: valueOne)
}
//便利构造器
override convenience init(valueOne: Int){
self.init(valueOne: valueOne);
}
}
关于类的构造器的使用在使用的时候,细节方面需要要注意很多,通过查找一些资料,现总结如下:
规则1:当前类存在父类时,指定构造器器必须调用其直接父类的指定构造器,为保证继承的属性得以初始化。 规则2:便利构造器必须调用同一类中定义的其他构造器。而且最终会导致一个指定构造器被调用。
Swift 中类的构造过程包含两个阶段,被称为是二段式构造
第一阶段:每个存储型的值指定一个初值。
第二阶段:给当前类一个机会,在新实例准备使用之前进一步修改定制存储型的属性。
与OC的区别:Swift与OC的构造过程相似,区别在于阶段一,OC给每个属性赋值为0或者空值,但是Swift更为灵活,允许开发者指定自己所需的初始值(默认值)。
第一阶段:
第二阶段: 从顶部构造器链一直往下,每个构造器链中类的指定构造器都有机会进一步定制实例。构造器此时可以访问self、修改它的属性并调用实例方法等等。 最终,任意构造器链中的便利构造器可以有机会定制实例和使用self 。
注意1: 重写系统自带的默认构造器(虽然不是显式的),也要带上override修饰符 注意2: 重写父类指定构造器必须带上override,即使你的子类将父类的指定构造器重写成了便利构造器 注意3: 子类编写和父类便利构造器相匹配的子类构造器时,由于子类不能直接调用父类的便利构造器,并不能看做是对父类构造器的重写。所以子类中“重写”父类便利构造器时,不需要加override修饰符。
子类在默认情况下不会继承父类的构造器。但是如果满足特定条件,父类构造器还是是可以被自动继承的。 构造器的自动继承需要满足前提条件是:子类中引入的所有新属性都提供了默认值。 然后可分为两种情况:
情况1:子类没有定义任何指定构造器,它将自动继承所有父类的指定构造器。
class SuperClass {
var valueOne: Int
//指定构造器
init(valueOne: Int){
self.valueOne = valueOne
}
}
class SubClass: SuperClass {
var valueTwo:Int = 100 //子类的新引入属性
}
//自动继承了父类的构造器,这里被使用创建子类,子类新属性使用默认值
let subClass = SubClass(valueOne: 10)
print("subClass:(\(subClass.valueOne)) valueTwo(\(subClass.valueTwo))")
情况2:子类提供了所有父类指定构造器的实现(通过情况1继承过来的或者子类自定义实现),此时子类将自动继承所有父类的便利构造器。
class Animal{
var name:String
var age: Int
init(name:String, age:Int){
self.name = name
self.age = age
}
//父类的便利构造器
convenience init(name:String){
self.init(name:name, age:10)
}
}
class Person: Animal{
var nickName:String!
//实现了父类中的指定构造器
override init(name:String, age:Int){
super.init(name:name, age:age)
self.name = name
self.age = age + 2
}
}
let ps = Person(name: "zs", age: 18)
自动继承注意: 1.即使你在子类中添加了更多的便利构造器,这两条规则仍然适用。 2.对于情况 2,子类可以将父类的指定构造器实现为便利构造器。