required修飾符的使用規則
required修飾符只能用于修飾類初始化方法。
當子類含有異于父類的初始化方法時(初始化方法參數類型和數量異于父類),子類必須要實現父類的required初始化方法,并且也要使用required修飾符而不是override。
當子類沒有初始化方法時,可以不用實現父類的required初始化方法。
普通子類
在一般情況下,我們說到required修飾符,我們應該會想到的就是普通類(class)的init方法,比如這個類:
class MyClass{
var str: String?
init(str: String?) {
self.str = str
}
}
當我們定義MyClass的子類subClass并且實例化這個字類,我們一般會怎么做呢?我們通常情況下是這樣子的:
class MyClass{
var str: String?
init(str: String?) {
self.str = str
}
}
class MySubClass: MyClass{
}
var MySubClass(str: "Hello Swift")
大家已經注意到了,在實例化MySubClass的過程中,其實是繼承了MyClass的init初始化方法,接下來我們看看子類的初始化方法
子類的初始化方法
class MyClass{
var str: String?
init(str: String?) {
self.str = str
}
}
class MySubClass: MyClass{
override init(str: String?) {
super.init(str: str)
}
}
var MySubClass(str: "Hello Swift")
- 我們可以看到首先在init方法前加了override重載符號,表示MySubClass重寫了父類MyClass的init方法,接著就會調用父類中的init方法,并且把參數傳遞過去
- 同時你會看到super關鍵字,super并不是父類的意思,它只是一個編譯符號,只會去父類中尋找對應的方法和參數,在這個栗子中,它尋找的就是父類中的init方法,并且把參數傳遞過去
- 當然,在實際應用中,我們還會遇到子類的初始化方法參數類型和父類的初始化方法參數類型不同,我們就不用使用override重載符號,但是要把子類的初始化方法參數類型轉化為符合父類的初始化方法參數類型,然后把參數傳給父類:
class MyClass{
var str: String?
init(str: String?) {
self.str = str
}
}
class MySubClass: MyClass{
init(i: Int) {
super.init(str: String(i))
}
}
var MySubClass(i: 123)
required修飾符
我們給父類的init()方法加上required修飾符后會發生什么呢,我們來看看:
class MyClass {
var str:String
required init(str:String) {
self.str = str
}
}
class MySubClass:MyClass
{
init(i:Int) {
super.init(str:String(i))
}
// 編譯錯誤
}
MySubClass(i: 123)
如果你敲出上面的代碼,OK,你百分之兩百會報錯,因為你沒有實現父類中必須實現的方法,正確的寫法:
import Foundation
class MyClass{
var str: String?
required init(str: String?) {
self.str = str
}
}
class MySubClass: MyClass{
init(i: Int) {
super.init(str: String(i))
}
required init(str: String?) {
fatalError("init(str:) has not been implemented")
}
}
var MySubClass(i: 123)
從上面的代碼中,不難看出子類需要添加異于父類的初始化方法,必須要重寫有required的修飾符的初始化方法,并且也要使用required修飾符而不是override,請千萬注意!
如果子類中并沒有不同于父類的初始化方法,Swift會默認使用父類的初始化方法
class MyClass{
var str: String?
required init(str: String?) {
self.str = str
}
}
class MySubClass: MyClass{
}
var MySubClass(str: "hello swift")
在這種情況下,編譯器不會報錯,因為如果子類沒有任何初始化方法時,Swift會默認使用父類的初始化方法。在Apple的文檔中也有相關描述:
You do not have to provide an explicit implementation of a required initializer if you can satisfy the requirement with an inherited initialiser.