Swift 的構(gòu)造器(一)

前言

? ? ? 本文主要是Swift的構(gòu)造器相關(guān)知識,另加少部分的OC中的init方法(還有少許Java相關(guān)的構(gòu)造方法)尤揣,通過兩者的對比來加深對Swift構(gòu)造器的理解疙筹,畢竟Swift是要淘汰的OC的隔盛,所以主要研究Swift也是必然呕臂。

指定構(gòu)造器和便利構(gòu)造器

? ? ? ? Swift構(gòu)造器分為兩類,一類是指定構(gòu)造器(Designated Initializer)查坪,另一類是便利構(gòu)造器(Convenience Initializer)寸宏。

? ? ? 指定構(gòu)造器

? ? ? ? 指定構(gòu)造器在一個類中必須至少有一個, 因?yàn)樗穷惖淖钪饕獦?gòu)造器,沒有之一偿曙,所有類的實(shí)例的初始化必然會調(diào)用指定構(gòu)造器氮凝。以init開頭,參數(shù)名望忆、參數(shù)列表可以依照實(shí)際情況編寫罩阵。當(dāng)沒有自定義指定構(gòu)造器時,系統(tǒng)會自動生成一個不帶參數(shù)的默認(rèn)構(gòu)造器启摄,不帶參數(shù)的默認(rèn)構(gòu)造器稿壁,意味著類的定義中,成員變量一定要賦上默認(rèn)值歉备。當(dāng)有自定義指定構(gòu)造器時傅是,類的定義中,成員變量可以沒有默認(rèn)值蕾羊,但是會在調(diào)用指定構(gòu)造器時給其賦值喧笔,并且賦值時機(jī)要在調(diào)用父類的指定構(gòu)造器之前(如果這個類有父類時)。舉個例子龟再,先定義一個基類书闸。

```

class Person {

? ? ? // 成員變量 name 、 sex都是沒有賦值

? ? ? ?var name:String

? ? ? ?var sex:String

? ? ? ?init(name:String, sex:String) {

? ? ? ? ? ? // 在指定構(gòu)造器中給成員變量賦值

? ? ? ? ? ? self.name = name

? ? ? ? ? ? self.sex = sex

? ? ? ?}

}

```

? 在這個基類Person中利凑,成員變量 name和sex在定義時都沒有賦值浆劲,只是指定數(shù)據(jù)類型嫌术,相關(guān)的賦值是在指定構(gòu)造器init(name:String, sex:String)中完成的。如果把Person類改成下面這樣

```

? ?// 這是個錯誤的定義

? ? class Person {

? ? ? ? ? var name:String

? ? ? ? ? var sex:String

? ? }

```

這個時候Xcode直接報錯:

這里報錯第一行顯示是Person沒有構(gòu)造器梳侨,其他行顯示name和sex沒有初始值蛉威,其實(shí)本質(zhì)來說日丹,是因?yàn)槌蓡T變量在Swift中已經(jīng)不是自動生成默認(rèn)值走哺,需要程序員自己指定。這里就需要提到一個不管是在Swift或者OC哲虾,還是Java或是其他面向?qū)ο蟮恼Z言都有的概念:某個類的實(shí)例被創(chuàng)建丙躏,其成員變量一定要有值。在上面的錯誤定義中束凑,因?yàn)镾wift不再為成員變量自動生成默認(rèn)值晒旅,如果程序員再不指定,這樣在創(chuàng)建實(shí)例時成員變量會沒有值汪诉,結(jié)果當(dāng)然是直接就報錯了废恋。如果我們像下面這樣稍微改動一下:

```

class Person {

? ? ? var name:String="李磊"

? ? ? var sex:String="男"

}

// 調(diào)用了Person自動生成的默認(rèn)指定構(gòu)造器(無參數(shù))

var per = Person()

```

結(jié)果成功運(yùn)行。在生成了per實(shí)例時扒寄,調(diào)用了自動生成的默認(rèn)指定構(gòu)造器鱼鼓,雖說是無參數(shù),但是Person類在定義時该编,直接就給name和sex賦值了迄本,所以這個per實(shí)例是成功被創(chuàng)建了。這里有一個不得不強(qiáng)調(diào)的一點(diǎn)课竣,Swift的指定構(gòu)造器本質(zhì)是嘉赎,確保本類的成員變量一定要被賦值,不是說一定要通過指定構(gòu)造器來賦值于樟。這個從上面改動的例子中可以看出(默認(rèn)構(gòu)造器并沒有給成員變量賦值)公条。

? ? ? ?當(dāng)某個類有父類時,在其指定構(gòu)造器中必須調(diào)用父類的指定構(gòu)造器迂曲,且在調(diào)用父類的指定構(gòu)造器前赃份,必須得確保這個類的成員變量必須得有值。為證明這些奢米,再定義一個Man類繼承自Person類

```

class Man:Person {

? ? ? ?var education:String="本科"

? ? ? ?// age此處并沒有被賦值

? ? ? ?var age:Int

? ? ? ?init(name:String, sex:String, age:Int) {

? ? ? ? ? ? // 在調(diào)用父類的指定構(gòu)造器之前抓韩,先給成員變量age賦值

? ? ? ? ? ? self.age=age

? ? ? ? ? ? // 調(diào)用父類的指定構(gòu)造器

? ? ? ? ? ? super.init(nameStr: name, sexStr: sex)

? ? ? ? }

}

```

如果將上面的例子改成,在指定構(gòu)造器中先調(diào)用父類的指定構(gòu)造器鬓长,而后給成員變量age賦值谒拴,像下面一樣

```

class Man:Person {

? ? ? ?var education:String="本科"

? ? ? ?// age此處并沒有被賦值

? ? ? ?var age:Int

? ? ? ?init(name:String, sex:String, age:Int) {

? ? ? ? ? ? ? // 先調(diào)用父類的指定構(gòu)造器

? ? ? ? ? ? ?super.init(nameStr: name, sexStr: sex)

? ? ? ? ? ? ? // 再給成員變量age賦值

? ? ? ? ? ? ? self.age=age

? ? ? ? }

}

```

結(jié)果Xcode報錯。

因?yàn)閍ge在定義的位置并沒有被賦值涉波,所以在調(diào)用父類的指定構(gòu)造器時age無值英上。對此強(qiáng)調(diào)一點(diǎn):指定構(gòu)造器在調(diào)用父類的構(gòu)造器前炭序,一定要確保子類引入的成員變量要有值。

? ? ? 便利構(gòu)造器

? ? ? 由convenience關(guān)鍵字修飾苍日,是橫向代理惭聂。橫向代理的意思是,convenience構(gòu)造器中必須調(diào)用同一個類中的其他一個構(gòu)造器相恃,這個構(gòu)造器是指定構(gòu)造器或者便利構(gòu)造器都行辜纲,但是,如果是便利構(gòu)造器的話拦耐,convenience構(gòu)造器通過調(diào)用鏈(代理鏈)最終都得調(diào)用一個designated構(gòu)造器耕腾。舉個例子,將Person和Man類稍微改一下:

```

? ? ?class Person {

? ? ? ? ? ? var name:String

? ? ? ? ? ? var sex:String

? ? ? ? ? ? init(name:String) {

? ? ? ? ? ? ? ? self.name= name

? ? ? ? ? ? ? ? self.sex="男"

? ? ? ? ? ? }

? ? ? ? ? ? //指定構(gòu)造器可以有多個杀糯,但是至少有一個

? ? ? ? ? ?init(nameStr:String, sexStr:String) {

? ? ? ? ? ? ? ? self.name= nameStr

? ? ? ? ? ? ? ? self.sex= sexStr

? ? ? ? ? ? }

? ? ? ? ? ?//定義便利構(gòu)造器(使用convenience修飾)

? ? ? ? ? convenience init(nameString:String, sexString:String) {

? ? ? ? ? ? ? ? ? //這里的便利構(gòu)造器必須調(diào)用同類中的指定構(gòu)造器扫俺,因?yàn)镻erson是基類,便利構(gòu)造器無法沿著構(gòu)造器的調(diào)用鏈調(diào)用到父類指定構(gòu)造器固翰,因?yàn)榛愂菦]有父類的,Swift不是OC狼纬,OC中NSObject是所有對象的基類,而Swift是沒有這種“終極”基類的骂际。

? ? ? ? ? ? ? ? ? self.init(nameStr: nameString, sexStr: sexString)

? ? ? ? ? }

? ? ? ? ? convenience init(speakWord:String) {

? ? ? ? ? ? ? ? ? self.init(nameStr:"人類", sexStr:"")

? ? ? ? ? ? ? ? ? print("Person--\(speakWord)")

? ? ? ? ? }

? ? }


class Man:Person{

? ? ? ?var education:String="本科"

? ? ? ?var age:Int= 10

? ? ? ?override init(name:String) {

? ? ? ? ? ? ?//子類的指定構(gòu)造器中必須調(diào)用父類的指定構(gòu)造器

? ? ? ? ? ? ?super.init(name: name)

? ? ? ?}

? ? ? ?override init(nameStr:String, sexStr:String) {

? ? ? ? ? ? ?super.init(nameStr: nameStr, sexStr: sexStr)

? ? ? ?}

? ? ? ?init(name:String, sex:String, age:Int) {

? ? ? ? ? ? self.age= 20

? ? ? ? ? ? super.init(nameStr: name, sexStr: sex)

? ? ? ? }

? ? ? ?//定義指定構(gòu)造器與父類的便利構(gòu)造器一樣,這里不算重寫

? ? ? convenience init(showStr:String, age:Int) {

? ? ? ? ? ? ?//這里調(diào)用的是從父類繼承來的便利構(gòu)造器

? ? ? ? ? ? ?self.init(speakWord:"hello!")

? ? ? ? ? ? ?self.age= 20

? ? ? ? ? ? ?print("Man---\(showStr)")

? ? ? ?}

}

```

在改過后的Man類中疗琉,就不得不提構(gòu)造器的繼承。之前說過構(gòu)造器默認(rèn)是不繼承方援,但是在有些情況下没炒,會繼承。

1.子類沒有定義任何的指定構(gòu)造器, 那么就會自動從父類那里繼承所有的指定構(gòu)造器

2.如果子類中提供了所有父類指定構(gòu)造器犯戏,不管是通過規(guī)則1(沒有定義任何指定構(gòu)造器)繼承來的送火,還是自定義實(shí)現(xiàn)的,它將繼承所有父類的便利構(gòu)造器

在改后的Man類中先匪,將Person類中的指定構(gòu)造器都o(jì)verrider了种吸,滿足第二種情況,所以父類的便利構(gòu)造器都被繼承了呀非。對于上面的規(guī)則1坚俗,個人覺得其實(shí)還可以改的更通俗點(diǎn)兒,只要是子類沒有定義指定構(gòu)造器岸裙,子類會從父類那里繼承所有的構(gòu)造器(包括便利構(gòu)造器)猖败,有興趣的可以試下將Man類其他的構(gòu)造器都刪掉,只保留便利構(gòu)造器降允,在編寫便利構(gòu)造器時恩闻,會發(fā)現(xiàn)Person類的所有構(gòu)造方法都已被繼承。還有一點(diǎn)可以看出剧董,在Man類的便利構(gòu)造器中幢尚,調(diào)用的是從父類繼承來的便利構(gòu)造器( 這一句代碼:self.init(speakWord:"hello!") )破停,在該便利構(gòu)造器中又調(diào)用了“init(nameStr:String, sexStr:String)”這個指定構(gòu)造器,所以調(diào)用便利構(gòu)造器尉剩,最終都會沿著調(diào)用鏈調(diào)用到一個指定構(gòu)造器真慢。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市理茎,隨后出現(xiàn)的幾起案子黑界,更是在濱河造成了極大的恐慌,老刑警劉巖功蜓,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件园爷,死亡現(xiàn)場離奇詭異宠蚂,居然都是意外死亡式撼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門求厕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來著隆,“玉大人,你說我怎么就攤上這事呀癣∶榔郑” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵项栏,是天一觀的道長浦辨。 經(jīng)常有香客問我,道長沼沈,這世上最難降的妖魔是什么流酬? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮列另,結(jié)果婚禮上芽腾,老公的妹妹穿的比我還像新娘。我一直安慰自己页衙,他們只是感情好摊滔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著店乐,像睡著了一般艰躺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上眨八,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天腺兴,我揣著相機(jī)與錄音,去河邊找鬼踪古。 笑死含长,一個胖子當(dāng)著我的面吹牛券腔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拘泞,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纷纫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了陪腌?” 一聲冷哼從身側(cè)響起辱魁,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诗鸭,沒想到半個月后染簇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡强岸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年锻弓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝌箍。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡青灼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出妓盲,到底是詐尸還是另有隱情杂拨,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布悯衬,位于F島的核電站弹沽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏筋粗。R本人自食惡果不足惜策橘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望亏狰。 院中可真熱鬧役纹,春花似錦、人聲如沸暇唾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽策州。三九已至瘸味,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間够挂,已是汗流浹背旁仿。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枯冈。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓毅贮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尘奏。 傳聞我的和親對象是個殘疾皇子滩褥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 20- 枚舉,枚舉原始值,枚舉相關(guān)值,switch提取枚舉關(guān)聯(lián)值 Swift枚舉: Swift中的枚舉比OC中的枚...
    iOS_恒仔閱讀 2,278評論 1 6
  • 本章將會介紹 存儲屬性的初始賦值自定義構(gòu)造過程默認(rèn)構(gòu)造器值類型的構(gòu)造器代理類的繼承和構(gòu)造過程可失敗構(gòu)造器必要構(gòu)造器...
    寒橋閱讀 769評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理瑰煎,服務(wù)發(fā)現(xiàn),斷路器俗孝,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • 十天前才去看過大舅媽酒甸,不曾想昨天她竟然走了。差不多八月二十號赋铝,大舅去慶偉哥家?guī)退春⒆尤チ瞬迩冢挥芯藡屧诩摇R姷轿覀?..
    紫燕風(fēng)前舞閱讀 681評論 0 0
  • 1.form表單有什么作用柬甥?有哪些常用的input 標(biāo)簽饮六,分別有什么作用其垄? 作用是:收集填寫的信息苛蒲,提交給網(wǎng)站的后...
    饑人谷_js_chen閱讀 180評論 0 0