Swift中的required修飾符

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的過程中,其實是繼承了MyClassinit初始化方法,接下來我們看看子類的初始化方法

子類的初始化方法

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重寫了父類MyClassinit方法,接著就會調用父類中的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.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 樓主最近一直被初始化方法到底要用什么修飾符困擾,今天就來說說這個問題 通常情況下,一說到required修飾符,我...
    Ywaiting閱讀 513評論 0 0
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,890評論 18 139
  • 20- 枚舉,枚舉原始值,枚舉相關值,switch提取枚舉關聯值 Swift枚舉: Swift中的枚舉比OC中的枚...
    iOS_恒仔閱讀 2,313評論 1 6
  • Swift2.0 1.defer譯為延緩、推遲之意類似棧 注意作用域,其次是調用順序——即一個作用域結束(注意),...
    zeqinjie閱讀 3,407評論 0 50
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 3,857評論 0 6