深入解析Swift編程中的構(gòu)造方法
一、引言
構(gòu)造方法是一個(gè)類(lèi)創(chuàng)建對(duì)象最先也是必須調(diào)用的方法,在Objective-C中,開(kāi)發(fā)者更習(xí)慣稱(chēng)這類(lèi)方法為初始化方法。在Objective-C中的初始化方法與普通函數(shù)相比除了要以init抬頭外并無(wú)太嚴(yán)格的分界,而在Swift語(yǔ)言體系中,構(gòu)造方法與普通的方法分界十分嚴(yán)格,從格式寫(xiě)法上就有不同,普通方法函數(shù)要以func聲明,構(gòu)造方法統(tǒng)一為init命名,不需要func關(guān)鍵字聲明,不同的構(gòu)造方法采用方法重載的方式創(chuàng)建。
二、構(gòu)造方法的復(fù)寫(xiě)與重載
在Objective-C中,不同的初始化方法就是不同的函數(shù),這便不存在方法重載的概念。Swift中要?jiǎng)?chuàng)建自定義的構(gòu)造方法,需要開(kāi)發(fā)者對(duì)init構(gòu)造方法進(jìn)行重載操作。任何一個(gè)自定義的類(lèi),只要其有父類(lèi),除了可以繼承下來(lái)父類(lèi)已有的構(gòu)造方法外,還可以復(fù)寫(xiě)父類(lèi)的構(gòu)造方法,使其適用于自身。和Objective-C類(lèi)似,復(fù)寫(xiě)父類(lèi)的構(gòu)造方法時(shí),要在其中調(diào)用父類(lèi)的構(gòu)造方法,重載可以理解為一種特殊的復(fù)寫(xiě)父類(lèi)構(gòu)造方法,因此在重載的構(gòu)造方法中也要調(diào)用父類(lèi)的構(gòu)造方法。
創(chuàng)建一個(gè)繼承于NSObject的類(lèi),復(fù)寫(xiě)構(gòu)造方法,代碼示例如下:
class ClassOne: NSObject {
//聲明一個(gè)本類(lèi)特有的常量
var tip:Int
//復(fù)寫(xiě)父類(lèi)的構(gòu)造方法 需要用override關(guān)鍵字
override init() {
//構(gòu)造方法中要對(duì)所有成員常量完成創(chuàng)建
tip = 1;
//在創(chuàng)建完所有成員常量后 調(diào)用父類(lèi)構(gòu)造方法
super.init()
}
//重載構(gòu)造方法1
init(one:Int){
tip=one
super.init()
}
//重載構(gòu)造方法2 使用convenience關(guān)鍵字進(jìn)行修飾
convenience init(two:String) {
//使用convenience關(guān)鍵字進(jìn)行修飾的構(gòu)造方法要調(diào)用本類(lèi)的構(gòu)造方法進(jìn)行
self.init(one: two.characters.count)
}
//重載構(gòu)造方法3 使用required關(guān)鍵字進(jìn)行修飾 使用required關(guān)鍵字進(jìn)行修飾的構(gòu)造方法子類(lèi)必須繼承或復(fù)寫(xiě)
required init(three:Float) {
tip=10
super.init()
}
上面示例代碼中,不帶參數(shù)的init()方法為復(fù)寫(xiě)父類(lèi)的方法,因此需要使用關(guān)鍵字override來(lái)修飾。重載構(gòu)造方法1帶一個(gè)Int類(lèi)型的 參數(shù),父類(lèi)中并沒(méi)有這個(gè)構(gòu)造方法,但是在其實(shí)現(xiàn)中,依然需要調(diào)用父類(lèi)中的某個(gè)構(gòu)造方法完成。構(gòu)造方法2是一個(gè)帶String類(lèi)型參數(shù)的構(gòu)造方法,其用convenience關(guān)鍵字為構(gòu)造方法的一個(gè)修飾關(guān)鍵字,后面會(huì)介紹。構(gòu)造方法3為一個(gè)帶Float類(lèi)型參數(shù)的構(gòu)造方法,但其使用required關(guān)鍵字進(jìn)行了修飾,使用required關(guān)鍵字進(jìn)行修飾的構(gòu)造方法子類(lèi)必須繼承或者復(fù)寫(xiě)。構(gòu)造方法1,2,3都是對(duì)init()構(gòu)造方法的一種重載,但卻是3中類(lèi)型全然不同的構(gòu)造方法。
三、Designated構(gòu)造方法與Convenience構(gòu)造方法
Swift中的構(gòu)造方法分為Designated構(gòu)造方法與Convenience構(gòu)造方法兩類(lèi),Designated構(gòu)造方法也被稱(chēng)為指定構(gòu)造方法,Convenience構(gòu)造方法也被稱(chēng)為方便構(gòu)造方法。Designated構(gòu)造方法不加任何修飾關(guān)鍵字,Convenience構(gòu)造方法需要使用Convenience關(guān)鍵字進(jìn)行修飾??梢赃@樣理解,Convenience類(lèi)型的構(gòu)造方法是為了方便使用從Designated構(gòu)造方法中分支出來(lái)的構(gòu)造方法,官方文檔中有如下描述:
1.子類(lèi)Designated構(gòu)造方法中必須調(diào)用父類(lèi)的Designated構(gòu)造方法。
2.Convenience構(gòu)造方法中必須調(diào)用當(dāng)前類(lèi)的構(gòu)造方法。
3.Convenience構(gòu)造方法歸根結(jié)底要調(diào)用到Designated構(gòu)造方法。
官方文檔的一張圖可以清晰的描述上述關(guān)系:

四、構(gòu)造方法的繼承關(guān)系
關(guān)于子類(lèi)繼承父類(lèi)的構(gòu)造方法有這樣幾個(gè)特性:
1.如果子類(lèi)沒(méi)有復(fù)寫(xiě)任何父類(lèi)的構(gòu)造方法,則默認(rèn)子類(lèi)將繼承所有父類(lèi)的構(gòu)造方法,包括Designated構(gòu)造方法與Convenience構(gòu)造方法。
2.如果子類(lèi)復(fù)寫(xiě)了父類(lèi)某一構(gòu)造方法,則子類(lèi)默認(rèn)不在繼承所有父類(lèi)的構(gòu)造方法,對(duì)于Designated類(lèi)型的構(gòu)造方法,子類(lèi)復(fù)寫(xiě)了哪些,哪些才能夠被使用,對(duì)于Convenienve類(lèi)型的構(gòu)造方法,子類(lèi)復(fù)寫(xiě)的其調(diào)用的Designated構(gòu)造方法后會(huì)被自動(dòng)繼承。
3.如果父類(lèi)中的構(gòu)造方法是required修飾的,則子類(lèi)必須進(jìn)行繼承或復(fù)寫(xiě)。
曾經(jīng)有朋友和我抱怨,Objective-C中的繼承是一種十分不人性,它強(qiáng)制子類(lèi)繼承所有父類(lèi)的方法與屬性無(wú)論子類(lèi)是否需要,分析上面的一些規(guī)則可以發(fā)現(xiàn),Swift與Objective-C相比,在構(gòu)造方法方面語(yǔ)法會(huì)更加嚴(yán)格,這樣做在編程上更加安全。在Objective-C中,子類(lèi)將被強(qiáng)制繼承所有父類(lèi)的初始化方法,這樣開(kāi)發(fā)者在使用時(shí)常常會(huì)出現(xiàn)疑惑,有時(shí)一個(gè)子類(lèi)往往有特定的初始化方法,僅僅通過(guò)父類(lèi)的初始化方法不能夠正確的完成初始化,在編程時(shí),往往需要特殊注釋來(lái)提示開(kāi)發(fā)者。Swift設(shè)定的這些構(gòu)造方法原則可以將無(wú)關(guān)的父類(lèi)構(gòu)造方法剔除在外,在編程時(shí)更加嚴(yán)格安全,減少疑惑與不可控因素。
五、構(gòu)造方法的實(shí)現(xiàn)原則
無(wú)論Designated類(lèi)型的構(gòu)造方法還是Convenience類(lèi)型的構(gòu)造方法,只要其有父類(lèi),最終都要實(shí)現(xiàn)父類(lèi)的Designated構(gòu)造方法。Swift語(yǔ)言要求,在構(gòu)造方法中要完成所有成員常量或者變量的構(gòu)造或賦值(optional值除外)。在對(duì)成員常量或變量進(jìn)行構(gòu)造賦值時(shí),要在調(diào)用父類(lèi)的初始化方法之前,這里還有一點(diǎn)需要注意,父類(lèi)的成員屬性也會(huì)被子類(lèi)繼承,如果要在子類(lèi)復(fù)寫(xiě)的父類(lèi)方法中對(duì)繼承來(lái)的父類(lèi)成員屬性進(jìn)行重新構(gòu)造或賦值,則必須在調(diào)用父類(lèi)構(gòu)造方法之后,例如創(chuàng)建ClassTwo類(lèi)繼承于ClassOne,復(fù)寫(xiě)方法如下:
class ClassTwo: ClassOne {
//子類(lèi)自己的屬性
let tipTwo:Int
override init() {
//調(diào)用父類(lèi)構(gòu)造方法前進(jìn)行自己屬性的構(gòu)造
tipTwo = 1
//調(diào)用父類(lèi)構(gòu)造方法
super.init()
//對(duì)從父類(lèi)繼承來(lái)的屬性進(jìn)行重構(gòu)造
tip = 1000;
}
required init(three: Float) {
fatalError("init(three:) has not been implemented")
}
}
Swift語(yǔ)言這種強(qiáng)制化得構(gòu)造規(guī)則,能夠保證一個(gè)類(lèi)在完成構(gòu)造時(shí),其內(nèi)部的所有屬性都構(gòu)造完成。在使用Objective-C進(jìn)行開(kāi)發(fā)時(shí),很多初學(xué)者都可能會(huì)遇到這樣一種情況,完成了某個(gè)類(lèi)的初始化,但向類(lèi)的屬性進(jìn)行賦值時(shí)卻沒(méi)有成功,因?yàn)镺bjective-C中并沒(méi)有這樣的語(yǔ)法,在類(lèi)初始化成功后,其屬性是否初始化了完全取決于開(kāi)發(fā)者,Swift優(yōu)化了這一設(shè)計(jì)。
綜上可以了解,Swift語(yǔ)言雖然更加嚴(yán)格,卻將更多本來(lái)需要開(kāi)發(fā)者注意的地方交由了編譯器,實(shí)際上是減輕了開(kāi)發(fā)者的負(fù)擔(dān)。
相關(guān)文章
詳解Swift中的數(shù)據(jù)類(lèi)型類(lèi)型轉(zhuǎn)換
Swift中的類(lèi)型轉(zhuǎn)換可以結(jié)合類(lèi)的繼承等面向?qū)ο蟮木幊烫匦詠?lái)進(jìn)行,本文中我們就來(lái)詳解Swift中的數(shù)據(jù)類(lèi)型類(lèi)型轉(zhuǎn)換,需要的朋友可以參考下2016-07-07
Swift中Optional值的鏈?zhǔn)秸{(diào)用學(xué)習(xí)筆記
這篇文章主要介紹了Swift中Optional值的鏈?zhǔn)秸{(diào)用學(xué)習(xí)筆記,Optional鏈?zhǔn)荢wift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-07-07
Swift語(yǔ)言中的一些訪問(wèn)控制設(shè)置詳解
這篇文章主要介紹了Swift語(yǔ)言中的一些訪問(wèn)控制設(shè)置詳解,是Swift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-11-11
swift中defer幾個(gè)簡(jiǎn)單的使用場(chǎng)景詳解
在Swift 2.0中,Apple提供了defer關(guān)鍵字,讓我們可以實(shí)現(xiàn)同樣的效果,這篇文章主要介紹了關(guān)于swift中defer幾個(gè)簡(jiǎn)單的使用場(chǎng)景的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用defer具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧。2018-03-03
Swift語(yǔ)言中的函數(shù)學(xué)習(xí)教程
這篇文章主要介紹了Swift語(yǔ)言中的函數(shù)學(xué)習(xí)教程,著重講了Swift函數(shù)的參數(shù)傳遞用法,需要的朋友可以參考下2015-11-11
Swift?Package?技巧及混編兼容問(wèn)題詳解
這篇文章主要為大家介紹了Swift?Package?技巧及混編兼容問(wèn)題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Swift如何調(diào)用Objective-C的可變參數(shù)函數(shù)詳解
這篇文章主要給大家介紹了關(guān)于Swift如何調(diào)用Objective-C的可變參數(shù)函數(shù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用swift具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03

