Swift開發(fā)標(biāo)準(zhǔn)教程-構(gòu)造器和析構(gòu)器_第1頁
Swift開發(fā)標(biāo)準(zhǔn)教程-構(gòu)造器和析構(gòu)器_第2頁
Swift開發(fā)標(biāo)準(zhǔn)教程-構(gòu)造器和析構(gòu)器_第3頁
Swift開發(fā)標(biāo)準(zhǔn)教程-構(gòu)造器和析構(gòu)器_第4頁
Swift開發(fā)標(biāo)準(zhǔn)教程-構(gòu)造器和析構(gòu)器_第5頁
已閱讀5頁,還剩51頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

構(gòu)造器和析構(gòu)器10.1值類型的構(gòu)造器10.2類的構(gòu)造器10.3可失敗構(gòu)造器10.4構(gòu)造器的特殊情況10.5設(shè)置默認(rèn)值10.6析構(gòu)器10.7綜合案例10.8上機(jī)實(shí)踐10.1值類型的構(gòu)造器10.1.1默認(rèn)構(gòu)造器10.1.2自定義構(gòu)造器10.1.3構(gòu)造器代理10.1.1默認(rèn)構(gòu)造器值類型的默認(rèn)構(gòu)造器只是針對結(jié)構(gòu)的,它不適用于枚舉類型。這個默認(rèn)構(gòu)造器將結(jié)構(gòu)實(shí)例的屬性都設(shè)為默認(rèn)值。默認(rèn)值都是在結(jié)構(gòu)屬性聲明中指定的。其實(shí)值類型的默認(rèn)構(gòu)造器我們在前面的章節(jié)中見過,在對結(jié)構(gòu)進(jìn)行實(shí)例化時使用的就是值類型的默認(rèn)構(gòu)造器。10.1.2自定義構(gòu)造器本小節(jié)將講解自定義構(gòu)造器的一些內(nèi)容。1.不帶參數(shù)的自定義構(gòu)造器構(gòu)造器在創(chuàng)建某個特定類型的新實(shí)例時被調(diào)用。它的最簡形式類似于一個不帶任何參數(shù)的實(shí)例方法,被稱為不帶參數(shù)的自定義構(gòu)造器,其語法形式如下:init(){

//在此處執(zhí)行構(gòu)造過程}2.帶有參數(shù)的自定義構(gòu)造器在自定義構(gòu)造器中是可以添加參數(shù)的,即構(gòu)成帶有參數(shù)的自定義構(gòu)造器,其語法形式如下:init(參數(shù)名1:數(shù)據(jù)類型,參數(shù)名2:數(shù)據(jù)類型,…){

…//在此處執(zhí)行構(gòu)造過程}帶有參數(shù)的自定義構(gòu)造器的調(diào)用形式如下:let/var對象名=值類型的類型名(參數(shù)名1:參數(shù)值,參數(shù)名2:參數(shù)值,…)2.帶有參數(shù)的自定義構(gòu)造器在使用帶有參數(shù)的構(gòu)造器時需要注意以下幾點(diǎn):(1)在使用自定義構(gòu)造器以后,就不可以再使用默認(rèn)的構(gòu)造器了。(2)在一個值類型中,不可以使用具有相同參數(shù)名,并且參數(shù)個數(shù)一致的構(gòu)造器。這樣會導(dǎo)致程序出現(xiàn)錯誤,就像在函數(shù)中不可以使用相同的函數(shù)一樣。(3)在一個值類型中定義了多個構(gòu)造器,在調(diào)用時,也只可以為一個對象調(diào)用一個構(gòu)造器,剩下的構(gòu)造器是不會執(zhí)行的。(4)在調(diào)用構(gòu)造器時,主要通過構(gòu)造器中的參數(shù)名和類型來確定應(yīng)該被調(diào)用的構(gòu)造器。正因?yàn)閰?shù)如此重要,如果在定義構(gòu)造器時沒有提供參數(shù)的外部名字,Swift會為每個構(gòu)造器的參數(shù)自動生成一個跟內(nèi)部名字相同的外部名。(5)如果開發(fā)者不希望為構(gòu)造器的某個參數(shù)提供外部名字,可以使用下劃線(_)來顯式描述它的外部名,以此重寫上面所說的默認(rèn)行為。10.1.3構(gòu)造器代理構(gòu)造器代理其實(shí)就是通過調(diào)用其它構(gòu)造器來完成實(shí)例的部分構(gòu)造過程。它能減少多個構(gòu)造器間的代碼重復(fù),從而提高代碼的可讀性,以及減少編程時間。值類型(結(jié)構(gòu)體和枚舉類型)不支持繼承,所以構(gòu)造器代理的過程相對簡單,因?yàn)樗鼈冎荒艽斫o提供給它的構(gòu)造器。根據(jù)調(diào)用構(gòu)造器參數(shù)的有無,構(gòu)造器代理也可以分為兩種形式:不帶參數(shù)的構(gòu)造器代理和帶參數(shù)的構(gòu)造器代理。以下就是對它們的詳細(xì)介紹。1.不帶參數(shù)的構(gòu)造器代理不帶參數(shù)的構(gòu)造器代理就是在調(diào)用另一個構(gòu)造器時,該構(gòu)造器是沒有參數(shù)的,其形式如下:init(){…}init(參數(shù)名1.數(shù)據(jù)類型){…self.init()…}2.帶有參數(shù)的構(gòu)造器代理帶參數(shù)的構(gòu)造器代理就是在調(diào)用另一個構(gòu)造器時,該構(gòu)造器是具有參數(shù)的,其形式如下:init(參數(shù)名1:數(shù)據(jù)類型,參數(shù)名2.:數(shù)據(jù)類型,…){…}init(參數(shù)名2.數(shù)據(jù)類型){…self.init(參數(shù)名1:參數(shù)值,參數(shù)名2:參數(shù)值,…)…}10.2類的構(gòu)造器類的構(gòu)造器只可以在類的實(shí)例進(jìn)行初始化時所使用的。本節(jié)將講解關(guān)于類的構(gòu)造器的一些內(nèi)容,如默認(rèn)構(gòu)造器、自定義構(gòu)造器、構(gòu)造器代理、類的兩段式構(gòu)造過程以及構(gòu)造器的繼承和重寫等。10.2.1默認(rèn)構(gòu)造器在類中也有默認(rèn)的構(gòu)造器,它和結(jié)構(gòu)中默認(rèn)構(gòu)造器的功能一樣,都是將簡單的創(chuàng)建一個所有屬性值都為默認(rèn)值的實(shí)例。在類一章中,我們使用的就是默認(rèn)構(gòu)造器來對實(shí)例化的對象進(jìn)行的初始化。10.2.2自定義構(gòu)造器在類中,除了可以有默認(rèn)構(gòu)造器,還可以有自定義構(gòu)造器。在類中自定義構(gòu)造器分為兩種:一種是指定構(gòu)造器;另一種是便利構(gòu)造器。1.指定構(gòu)造器指定構(gòu)造器是類中最主要的構(gòu)造器。指定構(gòu)造器將初始化類中提供的所有屬性。指定構(gòu)造器其實(shí)就是值類型的自定義構(gòu)造器,可以分為兩種:一種是不帶參數(shù)的指定構(gòu)造器,一種是帶有參數(shù)的指定構(gòu)造器。以下對這兩種構(gòu)造器的詳細(xì)講解。(1)不帶參數(shù)的指定構(gòu)造器不帶參數(shù)的指定構(gòu)造器的語法形式如下:init(){

…}不帶參數(shù)的指定構(gòu)造器的調(diào)用形式如下:let/var對象名=類名()(2)帶有參數(shù)的指定構(gòu)造器帶有參數(shù)的指定構(gòu)造器的語法形式如下:init(參數(shù)名1:數(shù)據(jù)類型,參數(shù)名2:數(shù)據(jù)類型,…){

…}帶有參數(shù)的指定構(gòu)造器的調(diào)用形式如下:let/var對象名=類名(參數(shù)名1:參數(shù)值,參數(shù)名2:參數(shù)值,…)2.便利構(gòu)造器便利構(gòu)造器是類中特有的一個自定義構(gòu)造器,它是比較次要的、輔助型的構(gòu)造器。開發(fā)者可以定義便利構(gòu)造器來調(diào)用同一個類中的指定構(gòu)造器,并為其參數(shù)提供默認(rèn)值,也可以定義便利構(gòu)造器來創(chuàng)建一個特殊用途或特定輸入的實(shí)例。該構(gòu)造器也可以根據(jù)參數(shù)的有無分為:不帶參數(shù)和有參數(shù)的便利構(gòu)造器。(1)不帶參數(shù)的便利構(gòu)造器不帶參數(shù)的便利構(gòu)造器的定義形式如下:convenienceinit(){

…}不帶參數(shù)的便利構(gòu)造器的調(diào)用形式如下:let/var對象名=類名()(2)帶有參數(shù)的便利構(gòu)造器帶有參數(shù)的便利構(gòu)造器的定義形式如下:convenienceinit(參數(shù)名1.數(shù)據(jù)類型,參數(shù)名2.數(shù)據(jù)類型,…){

…}帶有參數(shù)的便利構(gòu)造器的調(diào)用形式如下:let/var對象名=類名(參數(shù)名1:參數(shù)值,參數(shù)名2:參數(shù)值,…)10.2.3構(gòu)造器代理類的構(gòu)造器代理實(shí)現(xiàn)規(guī)則和形式是非常麻煩的。因?yàn)轭惪梢詫?shí)現(xiàn)繼承,對于類在繼承時的構(gòu)造器代理,我們會在構(gòu)造器的繼承和重載中講解。以下主要講解在基類(基類就是不繼承任何的類)中的構(gòu)造器代理。這是在類中比較簡單的構(gòu)造器代理。對于基類中的構(gòu)造器代碼其實(shí)我們在自定義構(gòu)造器中已經(jīng)存在了,在定義便利構(gòu)造器時就使用到了構(gòu)造器代理。10.2.4類的兩段式構(gòu)造過程Swift中類的構(gòu)造過程包含兩個階段。第一個階段,每個存儲型屬性通過引入它們的類的構(gòu)造器來設(shè)置初始值。當(dāng)每一個存儲型屬性值被確定后,第二階段開始,它給每個類一次機(jī)會在新實(shí)例準(zhǔn)備使用之前進(jìn)一步定制它們的存儲型屬性。所以Swift中類的構(gòu)造過程被稱為兩段式構(gòu)造過程。兩段式構(gòu)造過程的使用可以讓構(gòu)造過程變得更加安全。因?yàn)樵谑褂脙啥问綐?gòu)造過程時,編譯器將執(zhí)行4種有效的安全檢查,以確保兩段式構(gòu)造過程能順利完成:10.2.4類的兩段式構(gòu)造過程安全檢查1:指定構(gòu)造器必須保證它所在類的所有屬性都必須先初始化完成,之后才能將其它構(gòu)造任務(wù)向上代理給父類中的構(gòu)造器。安全檢查2:指定構(gòu)造器必須先向上代理調(diào)用父類構(gòu)造器,然后再為繼承的屬性設(shè)置新值。如果沒這么做,指定構(gòu)造器賦予的新值將被父類中的構(gòu)造器所覆蓋。安全檢查3:便利構(gòu)造器必須先代理調(diào)用同一類中的其它構(gòu)造器,然后再為任意屬性賦新值。如果沒這么做,便利構(gòu)造器賦予的新值將被同一類中其它指定構(gòu)造器所覆蓋。安全檢查4:構(gòu)造器在第一階段構(gòu)造完成之前,不能調(diào)用任何實(shí)例方法、不能讀取任何實(shí)例屬性的值,也不能引用self的值。以下是兩段式構(gòu)造過程中基于上述安全檢查的構(gòu)造流程:1.階段1某個指定構(gòu)造器或便利構(gòu)造器被調(diào)用。完成新實(shí)例內(nèi)存的分配,但此時內(nèi)存還沒有被初始化。指定構(gòu)造器確保其所在類引入的所有存儲型屬性都已賦初值。存儲型屬性所屬的內(nèi)存完成初始化。指定構(gòu)造器將調(diào)用父類的構(gòu)造器,完成父類屬性的初始化。這個調(diào)用父類構(gòu)造器的過程沿著構(gòu)造器鏈一直往上執(zhí)行,直到到達(dá)構(gòu)造器鏈的最頂部。當(dāng)?shù)竭_(dá)了構(gòu)造器鏈最頂部,且已確保所有實(shí)例包含的存儲型屬性都已經(jīng)賦值,這個實(shí)例的內(nèi)存被認(rèn)為已經(jīng)完全初始化。此時階段1完成。2.階段2從頂部構(gòu)造器鏈一直往下,每個構(gòu)造器鏈中類的指定構(gòu)造器都有機(jī)會進(jìn)一步定制實(shí)例。構(gòu)造器此時可以訪問self、修改它的屬性并調(diào)用實(shí)例方法等等。最終,任意構(gòu)造器鏈中的便利構(gòu)造器可以有機(jī)會定制實(shí)例和使用self。以下會以一個圖的形式為讀者介紹構(gòu)造的第二階段,如圖10-2所示。10.2.5構(gòu)造器的繼承和重載在類的構(gòu)造器代理中提到了,類的構(gòu)造器代理實(shí)現(xiàn)規(guī)則和形式是非常麻煩的,因?yàn)轭惪梢詫?shí)現(xiàn)繼承。以下是構(gòu)造器之間的代理調(diào)用使用規(guī)則:指定構(gòu)造器必須要調(diào)用其直接父類中的指定構(gòu)造器便利構(gòu)造器必須調(diào)用同一類中定義的其它構(gòu)造器。便利構(gòu)造器必須最終以調(diào)用一個指定構(gòu)造器結(jié)束。1.構(gòu)造器的繼承子類在默認(rèn)情況下不會繼承父類的構(gòu)造器。。但是如果滿足特定條件,父類構(gòu)造器是可以被自動繼承的。以下是實(shí)現(xiàn)自動繼承的兩個規(guī)則:(1)規(guī)則1如果子類沒有定義任何指定構(gòu)造器,它將自動繼承所有父類的指定構(gòu)造器。(2)規(guī)則2如果子類提供了所有父類指定構(gòu)造器的實(shí)現(xiàn)——無論是通過規(guī)則1繼承過來的,還是提供了自定義實(shí)現(xiàn)——它將自動繼承所有父類的便利構(gòu)造器。2.構(gòu)造器的重載在類中出了可以對屬性、方法以及下標(biāo)腳本進(jìn)行重載外,還可以對父類中的構(gòu)造器進(jìn)行重載。以下就對指定構(gòu)造器和便利構(gòu)造器進(jìn)行重載的詳細(xì)講解。(1)重載指定構(gòu)造器開發(fā)者如果想要重載父類中的指定構(gòu)造器,就需要在子類中實(shí)現(xiàn)重載,不僅需要在指定構(gòu)造器的前面加上override,還需要在重載的構(gòu)造器中調(diào)用父類的構(gòu)造器。(2)重載便利構(gòu)造器開發(fā)者如果想要重載父類中的便利構(gòu)造器,就需要在子類中實(shí)現(xiàn)重載,并且重載時必須通過調(diào)用同一類中提供的其它指定構(gòu)造器來實(shí)現(xiàn)。10.2.6必要構(gòu)造器在類的構(gòu)造器前添加required修飾符,可以定義一個必要構(gòu)造器,它表明所有該類的子類都必須實(shí)現(xiàn)該構(gòu)造器。在子類重寫父類的必要構(gòu)造器時,必須在子類的構(gòu)造器前也添加required修飾符,表明該構(gòu)造器要求也應(yīng)用于繼承鏈后面的子類。在重寫父類中必要的指定構(gòu)造器時,不需要添加override修飾符。10.3可失敗構(gòu)造器10.3.1定義可失敗構(gòu)造器10.3.2枚舉類型的可失敗構(gòu)造器10.3.3類的可失敗構(gòu)造器10.3.4構(gòu)造失敗的傳遞10.3.5重寫一個可失敗構(gòu)造器10.3.6可失敗構(gòu)造器init!10.3.1定義可失敗構(gòu)造器可失敗構(gòu)造器的定義就是在init關(guān)鍵字后面加添問號?就可以了??墒?gòu)造器會創(chuàng)建一個類型為自身類型的可選類型的對象。開發(fā)者通過returnnil語句來表明可失敗構(gòu)造器在何種情況下應(yīng)該“失敗”。10.3.2枚舉類型的可失敗構(gòu)造器開發(fā)者可以通過一個帶一個或多個參數(shù)的可失敗構(gòu)造器來獲取枚舉類型中特定的枚舉成員。如果提供的參數(shù)無法匹配任何枚舉成員,則構(gòu)造失敗。10.3.3類的可失敗構(gòu)造器值類型(也就是結(jié)構(gòu)體或枚舉)的可失敗構(gòu)造器,可以在構(gòu)造過程中的任意時間點(diǎn)觸發(fā)構(gòu)造失敗。例如在前面的例子中,結(jié)構(gòu)Animal的可失敗構(gòu)造器在構(gòu)造過程一開始就觸發(fā)了構(gòu)造失敗,甚至在species屬性被初始化前。而對類而言,可失敗構(gòu)造器只能在類引入的所有存儲型屬性被初始化后,以及構(gòu)造器代理調(diào)用完成后,才能觸發(fā)構(gòu)造失敗。10.3.4構(gòu)造失敗的傳遞類、結(jié)構(gòu)體、枚舉的可失敗構(gòu)造器可以橫向代理到類型中的其他可失敗構(gòu)造器。類似的,子類的可失敗構(gòu)造器也能向上代理到父類的可失敗構(gòu)造器。無論是向上代理還是橫向代理,如果開發(fā)者代理到的其他可失敗構(gòu)造器觸發(fā)構(gòu)造失敗,整個構(gòu)造過程將立即終止,接下來的任何構(gòu)造代碼不會再被執(zhí)行。10.3.5重寫一個可失敗構(gòu)造器和其他構(gòu)造器一樣,父類中的可失敗構(gòu)造器在子類中也是可以進(jìn)行重寫的?;蛘吣阋部梢杂米宇惖姆强墒?gòu)造器重寫一個父類的可失敗構(gòu)造器。10.3.6可失敗構(gòu)造器init!通常來說我們通過在init關(guān)鍵字后添加問號的方式(init?)來定義一個可失敗構(gòu)造器,但你也可以通過在init后面添加驚嘆號的方式來定義一個可失敗構(gòu)造器((init!)),該可失敗構(gòu)造器將會構(gòu)建一個對應(yīng)類型的隱式解包可選類型的對象。用戶可以在init?中代理到init!,反之亦然。你也可以用init?重寫init!,反之亦然。10.4構(gòu)造器的特殊情況10.4.1可選屬性類型10.4.2修改常量屬性10.4.1可選屬性類型開發(fā)者在定義類型時,如果包含邏輯上允許取值為空的存儲屬性,都需要將它定義為可選類型。無論存儲型屬性是因?yàn)闊o法在初始化時賦值,還是因?yàn)樗梢栽谥竽硞€時間點(diǎn)可以賦值為空。可選類型的屬性將自動初始化為空nil,表示這個屬性是故意在初始化時設(shè)置為空的。10.4.2修改常量屬性你可以在構(gòu)造過程中的任意時間點(diǎn)修改常量屬性的值,只要在構(gòu)造過程結(jié)束時是一個確定的值。一旦常量屬性被賦值,它將永遠(yuǎn)不可更改。10.5設(shè)置默認(rèn)值10.5.1在定義時直接賦值10.5.2在構(gòu)造器中賦值10.5.3使用閉包設(shè)置屬性的默認(rèn)值10.5.4使用函數(shù)設(shè)置默認(rèn)值10.5.1在定義時直接賦值在定義屬性時直接為屬性賦值,是開發(fā)者設(shè)置默認(rèn)值的一種最常用的方式,也是最簡單的一種方法。10.5.2在構(gòu)造器中賦值使用構(gòu)造器為屬性進(jìn)行賦值,其實(shí)我們在本章的10.5節(jié)之前的節(jié)中就見過了。10.5.3使用閉包設(shè)置屬性的默認(rèn)值如果某個存儲型屬性的默認(rèn)值需要一些定制或設(shè)置,你可以使用閉包為其提供定制的默認(rèn)值。每當(dāng)某個屬性所在類型的新實(shí)例被創(chuàng)建時,對應(yīng)的閉包會被調(diào)用,而它們的返回值會當(dāng)做默認(rèn)值賦值給這個屬性。使用閉包設(shè)置默認(rèn)值的語法形式如下:let\var屬性名:數(shù)據(jù)類型={

return某一值}()10.5.4使用函數(shù)設(shè)置默認(rèn)值如果某個存儲型屬性的默認(rèn)值需要一些定制或設(shè)置,開發(fā)者除了可以使用閉包為其提供定制的默認(rèn)值外,還可以實(shí)現(xiàn)函數(shù)為其定制默認(rèn)值。10.6析構(gòu)器10.6.1理解析構(gòu)器10.6.2析構(gòu)器的定義10.6.3使用析構(gòu)器10.6.4使用析構(gòu)器的注意事項(xiàng)10.6.5構(gòu)造器和析構(gòu)器的區(qū)別10.6.1理解析構(gòu)器10.6.2析構(gòu)器的定義析構(gòu)器需要用關(guān)鍵字deinit來定義,類似于狗仔器需要使用init來定義,其語法形式如下:deinit{

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論