一、構造函數的調用規則
swift規定了三條規則來限制構造函數之間的調用。
1、指定構造函數必須最終調用其直接父類的指定構造函數
2、便利構造函數必須調用當前類中定義的其他構造函數
3、便利構造函數必須最終導致一個指定構造函數被使用
class Person{
var name:String //這里不用加?是因為構造函數里邊賦值了,不賦值就要加上?
var age:Int
//指定構造函數
init(age:Int,name:String) {
self.name = name
self.age = age
}
//便利構造函數
convenience init(age:Int){
self.init(age: age,name: "張三")
}
}
class Teacher : Person{
var sex:String
//指定構造函數
init(age:Int,name:String,sex:String){
self.sex = sex
super.init(age: age, name: name)
}
//便利構造函數
convenience init(age:Int){
self.init(age: age, name: "王五", sex: "老頭")
}
}
var per = Person(age: 13)
print(per.name)
var tea:Teacher = Teacher(age:15,name:"李四",sex:"男")
print(tea.sex)
var tea2:Teacher = Teacher(age:38)
print(tea2.sex)
控制臺
張三
男
老頭
二、構造過程的安全檢查
swift中類的構造過程分為兩個階段即調用構造方法分為兩個階段
- 1、首先分配內存,初始化子類新增的存儲屬性,然后沿構造函數鏈晚上初始化每個父類的存儲屬性,到達函數鏈的頂端。此時,子類和父類的所有存儲屬性都有初始值。
- 2、從頂部的構造鏈往下,給每個類一次機會在新的實例準備使用之前修改存儲屬性,挑用實例方法等。
安全檢查一、
指定構造函數必須保證它所在類引入的所有存儲屬性確定之后才能完全初始化,之后才能將其他構造任務向上代理給父類中的構造函數。
這就是為什么self.sex = sex
要寫在 super.init(age: age, name: name)
上邊。
class Teacher : Person{
var sex:String
//指定構造函數
init(age:Int,name:String,sex:String){
self.sex = sex
super.init(age: age, name: name)
}
}
安全檢查二、
指定構造函數必須先向上代理調用父類的構造函數,然后再為繼承的屬性設置新值。否則設置的新值將被父類的構造函數所覆蓋
class Teacher : Person{
var sex:String
//指定構造函數
init(age:Int,name:String,sex:String){
self.sex = sex
self.name = "zhang"http://這個name將被父類的賦值操作覆蓋
super.init(age: age, name: name)
}
}
安全檢查三、
便利構造函數必須先調用同一類中的其他構造函數,然后再為任意屬性賦值新值,否則新值將被本類中的其他構造函數覆蓋
class Teacher : Person{
var sex:String
//指定構造函數
init(age:Int,name:String,sex:String){
self.sex = sex
super.init(age: age, name: name)
}
//便利構造函數
convenience init(age:Int){
self.sex = "zhang"http://這個name將被指定構造函數的賦值操作覆蓋
self.init(age: age, name: "王五", sex: "老頭")
}
}
//由于我看的書是swift2.0,swift更新到3.0之后這樣寫會直接報錯,但是至少原理是醬紫的不是。萬變不離其宗,報錯信息如下
//Use of 'self' in property access 'sex' before self.init initializes self
Snip20170627_1.png
安全檢查四、
構造函數再第一步分配內存完成之前,不能調用任何實例方法,不能讀取任何實例屬性的值
class Teacher : Person{
var sex:String
//指定構造函數
init(age:Int,name:String,sex:String){
self.sex = sex
self.description() //error
super.init(age: age, name: name)
}
func description(){
print("description")
}
}
三、構造函數的自動繼承
子類對父類構造函數的自動繼承有兩個規則
1、如果子類中定義的所有新屬性都有默認值,并且子類沒有自定義任何構造函數,那么子類將自動繼承父類的所有指定構造函數
2、如果子類提供了所有父類指定構造函數的實現,無論是通過規則1繼承的,還是提供了自定義實現,它將自動繼承所有父類額便利構造函數(即使屬性沒有默認值,只要實現了父類的所有指定構造函數,就會自動繼承父類的所有便利構造函數)。而且,子類可以將父類的指定構造函數實現為便利構造函數
//個人感覺這個東西沒什么用,你都定義了子類了,肯定要增加屬性或者方法,還不自己整自己的構造函數,還用父類的,丟人不丟人,哈哈
四、構造函數的重寫
重寫父類構造函數,跟重寫方法一樣。override即可