構造方法是一個類建立對象最早也是必須調用的方法,在Objective-C中,開發者更習慣稱這類方法爲初始化方法。在Objective-C中的初始化方法與普通函數相比除了要以init擡頭外並沒有太嚴格的分界,而在Swift語言體系中,構造方法與普通的方法分界十分嚴格,從格式寫法上就有不一樣,普通方法函數要以func聲明,構造方法統一爲init命名,不須要func關鍵字聲明,不一樣的構造方法採用方法重載的方式建立。編程
在Objective-C中,不一樣的初始化方法就是不一樣的函數,這便不存在方法重載的概念。Swift中要建立自定義的構造方法,須要開發者對init構造方法進行重載操做。任何一個自定義的類,只要其有父類,除了能夠繼承下來父類已有的構造方法外,還能夠複寫父類的構造方法,使其適用於自身。和Objective-C相似,複寫父類的構造方法時,要在其中調用父類的構造方法,重載能夠理解爲一種特殊的複寫父類構造方法,所以在重載的構造方法中也要調用父類的構造方法。安全
建立一個繼承於NSObject的類,複寫構造方法,代碼示例以下:ide
class ClassOne: NSObject { //聲明一個本類特有的常量 var tip:Int //複寫父類的構造方法 須要用override關鍵字 override init() { //構造方法中要對全部成員常量完成建立 tip = 1; //在建立完全部成員常量後 調用父類構造方法 super.init() } //重載構造方法1 init(one:Int){ tip=one super.init() } //重載構造方法2 使用convenience關鍵字進行修飾 convenience init(two:String) { //使用convenience關鍵字進行修飾的構造方法要調用本類的構造方法進行 self.init(one: two.characters.count) } //重載構造方法3 使用required關鍵字進行修飾 使用required關鍵字進行修飾的構造方法子類必須繼承或複寫 required init(three:Float) { tip=10 super.init() }
上面示例代碼中,不帶參數的init()方法爲複寫父類的方法,所以須要使用關鍵字override來修飾。重載構造方法1帶一個Int類型的 參數,父類中並無這個構造方法,可是在其實現中,依然須要調用父類中的某個構造方法完成。構造方法2是一個帶String類型參數的構造方法,其用convenience關鍵字爲構造方法的一個修飾關鍵字,後面會介紹。構造方法3爲一個帶Float類型參數的構造方法,但其使用required關鍵字進行了修飾,使用required關鍵字進行修飾的構造方法子類必須繼承或者複寫。構造方法1,2,3都是對init()構造方法的一種重載,但倒是3中類型全然不一樣的構造方法。函數
Swift中的構造方法分爲Designated構造方法與Convenience構造方法兩類,Designated構造方法也被稱爲指定構造方法,Convenience構造方法也被稱爲方便構造方法。Designated構造方法不加任何修飾關鍵字,Convenience構造方法須要使用Convenience關鍵字進行修飾。能夠這樣理解,Convenience類型的構造方法是爲了方便使用從Designated構造方法中分支出來的構造方法,官方文檔中有以下描述:優化
1.子類Designated構造方法中必須調用父類的Designated構造方法。ui
2.Convenience構造方法中必須調用當前類的構造方法。spa
3.Convenience構造方法歸根結底要調用到Designated構造方法。設計
官方文檔的一張圖能夠清晰的描述上述關係:code
關於子類繼承父類的構造方法有這樣幾個特性:對象
1.若是子類沒有複寫任何父類的構造方法,則默認子類將繼承全部父類的構造方法,包括Designated構造方法與Convenience構造方法。
2.若是子類複寫了父類某一構造方法,則子類默認不在繼承全部父類的構造方法,對於Designated類型的構造方法,子類複寫了哪些,哪些纔可以被使用,對於Convenienve類型的構造方法,子類複寫的其調用的Designated構造方法後會被自動繼承。
3.若是父類中的構造方法是required修飾的,則子類必須進行繼承或複寫。
曾經有朋友和我抱怨,Objective-C中的繼承是一種十分不人性,它強制子類繼承全部父類的方法與屬性不管子類是否須要,分析上面的一些規則能夠發現,Swift與Objective-C相比,在構造方法方面語法會更加嚴格,這樣作在編程上更加安全。在Objective-C中,子類將被強制繼承全部父類的初始化方法,這樣開發者在使用時經常會出現疑惑,有時一個子類每每有特定的初始化方法,僅僅經過父類的初始化方法不可以正確的完成初始化,在編程時,每每須要特殊註釋來提示開發者。Swift設定的這些構造方法原則能夠將無關的父類構造方法剔除在外,在編程時更加嚴格安全,減小疑惑與不可控因素。
不管Designated類型的構造方法仍是Convenience類型的構造方法,只要其有父類,最終都要實現父類的Designated構造方法。Swift語言要求,在構造方法中要完成全部成員常量或者變量的構造或賦值(optional值除外)。在對成員常量或變量進行構造賦值時,要在調用父類的初始化方法以前,這裏還有一點須要注意,父類的成員屬性也會被子類繼承,若是要在子類複寫的父類方法中對繼承來的父類成員屬性進行從新構造或賦值,則必須在調用父類構造方法以後,例如建立ClassTwo類繼承於ClassOne,複寫方法以下:
class ClassTwo: ClassOne { //子類本身的屬性 let tipTwo:Int override init() { //調用父類構造方法前進行本身屬性的構造 tipTwo = 1 //調用父類構造方法 super.init() //對從父類繼承來的屬性進行重構造 tip = 1000; } required init(three: Float) { fatalError("init(three:) has not been implemented") } }
Swift語言這種強制化得構造規則,可以保證一個類在完成構造時,其內部的全部屬性都構造完成。在使用Objective-C進行開發時,不少初學者均可能會遇到這樣一種狀況,完成了某個類的初始化,但向類的屬性進行賦值時卻沒有成功,由於Objective-C中並無這樣的語法,在類初始化成功後,其屬性是否初始化了徹底取決於開發者,Swift優化了這一設計。
綜上能夠了解,Swift語言雖然更加嚴格,卻將更多原本須要開發者注意的地方交由了編譯器,其實是減輕了開發者的負擔。
專一技術,熱愛生活,交流技術,也作朋友。
——琿少 QQ羣:203317592