五、构造方法的安全特性
Swift是一种十分注重类型安全的语言,这种语言特性的优势在于类在实例化后,所有的属性都是开发者明确可控的。Swift的编译器在类的构造方法中会进行4中安全性检查:
检查1:指定构造器中必须完成所有存储属性的赋值后才能调用父类的指定构造方法,示例如下:
class MyClassThree: MyClassTwo {
var param:Int
init(){
param = 100
super.init(name: "HS")
}
}
检查2:子类如果要自定义父类中存储属性的值,必须要调用父类的构造方法之后设置,示例如下:
class MyClassThree: MyClassTwo {
var param:Int
init(){
param = 100
super.init(name: "HS")
//重设继承父类属性的name值
self.name = "New"
}
}
检查3:如果便利构造方法中需要重新设置某些属性的值,必须在调用指定构造方法之后设置,否则会被覆盖。
检查4:在完成父类构造方法之前,不能使用self来引用属性。
六、构造方法的继承
Swift和Objective-C有很大不同,其构造方法不会被子类无条件的继承。Swift中类的构造方法的继承遵守下面两个原则:
1.如果子类没有定义任何的指定构造方法,则子类会默认继承父类所有的指定构造方法。
2.如果子类中提供了父类所有指定构造方法,无论是覆写的还是继承的,则子类会默认继承下来父类的便利构造方法。
上面两个原则可能有些难以理解,第1个原则实际上也说明子类如果定义了自己的指定构造方法,或者覆写了父类的某个指定构造方法,则子类不再继承父类所有的指定构造方法。第2个原则可以这样理解:因为所有便利构造方法最终都要调用到指定构造方法,所以只要子类中有提供这个便利构造方法需要调用的指定构造方法,这个便利构造方法就会被继承。
重写父类的指定构造方法需要使用override关键字,但是,便利构造方法并不存在重写的概念,因为其必须调用本类的其他构造方法,因此无论子类中定义的便利构造方法与父类是否相同,都是子类独立的便利构造方法。
七、可失败构造方法
在开发中还会遇到一种情况,某些构造方法需要传入一些参数,当参数不符合要求时,此构造过程可能会失败,这时,开发者可以使用可失败的构造方法来进行类型的构造,例如在类中创建可失败的构造方法示例示例如下:
class MyClassThree: MyClassTwo {
var param:Int
init(){
param = 100
super.init(name: "HS")
//重设继承父类属性的name值
self.name = "New"
}
init?(suc:Bool){
guard(suc)else{
return nil
}
param=1
super.init(name: "1")
}
}
八、必要构造方法
如果某些构造方法是类与其子类都必须实现的,则可以使用required关键字来将其修饰为必要的构造方法,子类必须继承或者覆写父类的必要构造方法,示例如下:
class MyClassThree: MyClassTwo {
var param:Int
required init(){
param = 100
super.init(name: "HS")
//重设继承父类属性的name值
self.name = "New"
}
init?(suc:Bool){
guard(suc)else{
return nil
}
param=1
super.init(name: "1")
}
}
还有一点需要注意,如果某些属性的值设置十分复杂,开发者可以使用闭包的方式来为属性设置初始值,示例如下:
class MyClassThree: MyClassTwo {
//注意 闭包的后面必须加(),否则会将param当成一个闭包属性来处理
var param:Int = {
return 6*6+6
}()
required init(){
param = 100
super.init(name: "HS")
//重设继承父类属性的name值
self.name = "New"
}
init?(suc:Bool){
guard(suc)else{
return nil
}
param=1
super.init(name: "1")
}
}
九、析构方法
当类实例将要被释放时,系统会自动调用类的析构方法,析构方法deinit()没有参数和返回值,并且只有类有析构方法,开发者可以在其中进行一些资源的释放操作,当var类型变量被赋值为nil时,实例会被释放。