窺探Swift之別具一格的Struct和Class

青玉伏案發表於2016-01-20

說到結構體和類,還是那句話,只要是接觸過程式設計的小夥伴們對這兩者並不陌生。但在Swift中的Struct和Class也有著令人眼前一亮的特性。Struct的功能變得更為強大,Class變的更為靈活。Struct中不僅可以定義屬性,並且還可以在其中定義函式,這一點比較像Class的特性了。不過Struct畢竟是結構體,它還是不支援繼承等類特有的屬性的。今天這篇部落格就正兒八經的來搞一搞Swift中的Struct和Class。

當然,這篇部落格是比較基礎的,但是基礎的東西才是重要的東西呢,廢話不多說了,走起。

一. Struct (結構體)

結構體,說白了就是一組變數,這些變數有統一的命名。在Swift中,我們不僅可以在Struct中宣告變數併為變數設定預設值,而且可以在Struct中新增相應的函式。接下來我們就要建立一個Point結構體,裡邊有兩個屬性x座標和y座標,並且x座標和y座標的初始值為0。其中還有兩個方法,一個是display方法,負責輸出點的座標,並且還有一個setPoint方法,這個方法負責設定座標點。然後我們就要去這個結構體去宣告變數,並且呼叫其中的方法。

1.結構體型別的定義

使用struct關鍵字來宣告我們的結構體型別,結構體型別的名稱為MyPoint, 其中座標x, y為變數,其初始值為0。並且為我們的結構體新增了一個setMyPoint()方法和display()方法。

由上面的程式碼片段你也許會注意到在setMyPoint()方法關鍵字func前邊多了一個mutating關鍵字。在Struct中的函式,預設(不新增mutating關鍵字)的函式對Struct中屬性只有只讀許可權。如果你新增上mutating, 那麼該函式就對屬性持有讀寫的許可權。

2.結構體型別變數的宣告以及結構體函式的使用

接下來我們就利用上述“MyPoint”結構體型別來建立一個結構體型別變數。因為(x, y)值是有初始值的,所以在初始化結構體變數時不需要為其指定初始值。Struct型別的使用和Class使用是大同小異的。MyPoint()就類似於類的建構函式。我們宣告完變數,並分配記憶體空間後,我們對x, y的值進行列印可以看到x, y的初始值為0。具體如下所示:

我們可以呼叫訪問許可權為讀寫的setMyPoint()方法來改變結構體變數中屬性的值,下方就是把座標(10.0,20.0)賦值給myPoint變數,具體如下所示。

除了上述方法給結構體變數中的屬性賦值外,我們還可以通過建構函式給其屬性賦值。也就是在給變數分配記憶體空間時為其指定初始值,這一點就和類的建構函式即為相似了。具體方式如下圖片中的程式碼片段所示:

結構體就先聊到這兒,下面開始比較重要的部分:類(Class)

二. 類(Class)

Swift作為一門現代物件導向程式語言,怎麼能沒有類呢。關於Objc中的Class, 請參考我之前發表的一篇部落格《在Objective-C中淺談物件導向》, 其中淺談了Objective-C中物件導向的東西。今天就聊聊Swift中的類,雖然語言不通,但是Class還是大同小異的。本篇部落格的此部分注重Swift類中的語法已經使用方式,對物件導向的思想沒有做過多的陳述,因為我們的重點是在Swift程式設計,而不是物件導向程式設計。好~進入這一部分的主題。

1. 類的建立與構造器

為了簡單也是秉著由淺入深的原則,接下來將把上面MyPoint結構體型別使用類的形式來實現一下。簡單從語法上看兩者是大同小異的。下方截圖中的程式碼段是在上述MyPoint結構體修改而來的。改成下方MyPoint類做了兩點修改,第一點就是把struct關鍵字改成class關鍵字,

下方是MyPoint類的使用方法,雖然在上述類中沒有建構函式,會自動生成一個預設的無參建構函式。如下所示,呼叫的就是預設的無參建構函式進行的類的例項化。因為在類定義時我們為類中的屬性(即類的特徵)指定了初始值,所以將值進行列印就會顯示初始值了。

你在類定義時,沒有為其定義其他的建構函式,如果你呼叫了該未定義的建構函式,那麼就是你的不對了,編譯器就會報錯了,如下所示:

接下來我們就要為我們的MyPoint()類建立建構函式了。與其他現代程式語言(如C++, C#,Java等)不同,Swift的建構函式不是與類名同名的函式,而是使用特定的函式名init()來建立其建構函式。下方就是我們MyPoint類的建構函式,函式名當然是init了。在建構函式的形參列表中,我們可以為形參指定預設值,雖然下方只是一個建構函式,但是該建構函式與他的形參列表中的預設值一組合起來,可謂是打了一個漂亮的組合拳,使用起來也是灰常順手的。

給建構函式的形參列表指定預設值就省去了過載建構函式的麻煩。上面新增了一個建構函式,併為各個形參指定預設值,下方是其不同的呼叫方式,這在C++中應該過載4個建構函式才能實現的效果。Swift語言由此可見一斑呢~為之又眼前一亮,心中為之一振呢。具體呼叫方式如下:

2.物件的賦值與比較

在Swift中也是允許把一個類的變數的值通過賦值運算子(=)來賦值給另一個變數的。不過有一點要搞明白,如果類變數a的值賦值被類變數b,那麼變數a和b就指向同一塊記憶體區域。如果a中的例項變數中的值進行了修改,那麼例項b中的值也會進行修改。為了更好的表達這個思想,我們還是來張原理圖來介紹一下物件的賦值吧。具體的原理圖如下所示:

上面是原理,下方就是驗證。我們就宣告兩個變數a, b。 給a分配一個例項的空間,然後把a賦值給b。再接著就是改變a的值,觀察b中的屬性變化。具體如下所示:

如果要判斷兩個變數是否指向同一個例項,那麼我們就需要使用恆等運算子(===)了。下方就是判斷a是否和b指向同一個記憶體空間,具體程式碼如下所示:

3.屬性的懶載入(lazy)

在Swift的類中在對類進行初始化時,要對一些屬性進行初始化。如果某些屬性的初始化如果非常的耗費時間,那麼在這種情況下我們就可以該初始化耗時的屬性宣告為懶載入的屬性。就是在該屬性宣告的時候加上lazy關鍵字。被Lazy關鍵字修飾的變數會在使用時才會進行空間的分配。下方就是一個lazy的例項。

在下方例項中,除了MyPoint類,我們還需要定義一個MyCycle類。在MyCycle類中,使用到MyPoint類。在MyCycle類中的MyPoint屬性為懶載入屬性,具體請看程式碼,如下所示:

(1) 定義MyCycle類,在MyCycle類中,定義一個屬性為lazy的MyPoint類變數。如下所示:

(2)接下來就是使用MyCycle, 宣告MyCycle型別的變數,併為其分配MyCycle的型別例項。由下方例項可知,在呼叫MyCycle()建構函式時,MyCycle類中的point屬性並沒有對其進行初始化,此刻的point為nil。這樣就減少了MyCycle初始化的時間。

(3) lazy屬性point會在MyCycle例項物件在使用point屬性時才會對其進行初始化,下方是myCycle例項變數呼叫point屬性的程式碼片段,這時就明確的看到point是不為nil的。如下所示:

4. 計算屬性(Count Property)

計算屬性這一個特性在Objective-C中也是沒有的。什麼是計算屬性呢,一句話概括:計算屬性的值可以由其他屬性的值來計算得到,同時在給計算屬性賦值時也可以用來計算其他屬性的值。也許說起來比較拗口,理解起來也許回有些困難,那麼接下來來個小例項即可明白計算屬性是怎麼回事了。

下方我們建立一個名為Money的類,在Money類中有兩個屬性,一個是儲存屬性(普通屬性)名為CNY(代表著人民幣), 另一個是名為USD的計算屬性(代表美元)。在USD計算屬性的set方法中由USD的值計算CNY的值,在USD計算屬性的get方法中由CNY計算出USD的值,並返回。Money類的具體程式碼片段如下所示:

計算屬性在使用時和儲存屬性沒有什麼區別,下方是Money例項來呼叫其儲存屬性和計算屬性的程式碼段,已經結果輸出如下所示。下方程式碼段雖然簡單,但是你慢慢的去品還是很有味道的。先看第一部分,也就是第一次給USD賦值,當給USD賦值時,CNY的之會立即被計算出來。 而當我們給CNY賦值時,USD的值不會被立即計算出來,因為只有在使用USD時才會呼叫get方法,這時候才會根據CNY的值來計算USD的值。具體結果請看下方程式碼段:

5. 屬性觀察

屬性觀察是用來幹嘛的呢?說白了,屬性觀測器就是來觀察屬性的賦值情況的,屬性觀測器包括willSet()和didSet , willSet在屬性將要被賦值的時候被呼叫, didSet是在屬性被賦值後呼叫,關於這兩個屬性觀察函式,寫個例項就一目瞭然了。由下方例項可知,在willSet呼叫時,property屬性的值還為預設值,但是在didSet執行時,property的值已經成為被賦予的值了。

6. 例項方法與類方法

在Objc中,類方法是由+來修飾的,例項方法是由-號來修飾的。在Swift的方法中就沒有+或者-號進行修飾了,但是Swift中宣告方法時,多了一個class。普通方法沒有什麼特別之處,而類方法的宣告和定義需要在關鍵字func前新增class關鍵字。下方MyTestClass中定義了一個例項方法和一個類方法,並且給出了呼叫方式,如下所示:

今天部落格的內容就先到這兒,下篇部落格會涉及一些類的繼承和類中的方法和屬性的訪問許可權等其他一些關於類的東西。

打賞支援我寫出更多好文章,謝謝!

打賞作者

打賞支援我寫出更多好文章,謝謝!

窺探Swift之別具一格的Struct和Class

相關文章