在OC概念中經常提到的是類,但是在swift底層聲明中已經大部分使用了struct結構體,下面我們就來講解一下swift中的結構體.
一、類與結構體的區別
- 語義
- 類: 引用類型(引用語義),需要自己管理引用計數,引用值的變化
- 結構體:可以被直接持有及訪問,不會被引用,但是會被復制.也就是說,結構體的持有者是唯一的
拓展:
byte,short,int,long,float,double,decimal,char,bool 和 struct 統稱為值類型。
string,類等皆為引用類型。
值類型變量聲明后,不管是否已經賦值,編譯器為其分配內存。此時該值存儲於棧上;int i=10;執行之前為默認一個值0。
引用類型定義時在棧上開辟一個空間用來存放其在堆上的地址,當賦值或者實例化時候就會在堆上開辟一個空間,然后把堆中的地址存放在棧中,這時候棧就存放了其地址。
2. 內存管理方式
- 類: 類的實例只能通過引用來間接地訪問,類能有很多個持有者
- 結構體: 可以被直接持有及訪問,不會被引用,但是被復制,也就是說,結構體的持有者是唯一的
3. 共享代碼
- 類: 通過繼承來共享代碼
- 結構體(以及枚舉): 不能被繼承,想要在不同的結構體或者枚舉之間共享代碼,我們需要使用不同的技術,比如像是組合、泛型以及協議拓展
二、結構體
結構體為值類型
值類型意味着一個值變量被復制時,這個值本身也會被復制,而不只限於對這個值的引用的復制.
let a = 12 let b = a a += 1 print (a) // 13 print (b) // 12 b的值沒有根據a的值進行改變
而在swift中結構體的功能也被擴大化了,基本擁有了和類差不多的功能:
- 定義屬性
- 定義方法
- 定義getter和setter
- 可以定義初始化器來設置初始狀態
- 實現擴展的功能
- 遵循協議,並實現協議的方法
- 結構總是被復制,並且不使用引用計數
類具有結構不具備的附加功能:
- 繼承允許一個類繼承另一個類的特征
- 類型轉換使你能夠在運行時檢查和解釋類實例的類型
- 初始化器使一個類的實例能夠釋放它所分配的任何資源
- 引用計數允許多個引用到一個類實例
1.定義結構體和類,並且為其添加變量和方法
struct Resolution { var width = 0 var height = 0 func resolutionFun() { print("method of struct Resolution") } } class VideoMode { var resolution = Resolution() var interlaced = false var frameRate = 0.0 var name: String? func VideoMode() { print("method of class VideoMode") } }
2.類和結構體的初始化
let object Name = Class Name() let variable Name = Struct Name() let someResolution = Resolution() let someVideoMode = VideoMode()
訪問屬性
Swift中訪問屬性使用的是鏈式結構,訪問屬性的時候使用 .
print("The width of someResolution is \(someResolution.width)") print("The width of someVideoMode is \(someVideoMode.resolution.width)")
結構體的初始化
struct Resolution { var width = 0 var height = 0 } let resolution = Resolution(width:100,height:120) print("width:\(resolution.width),height:\(resolution.height)") 結果: width:100,height:120
首先要知道初始化器是系統本身的方法,我們只能去重寫或者重載它
重載就是將父類已有的方法通過擴充參數的形式重新定義一遍。
class VideoMode { var _name: String init(){ _name = "Jin" } init(name:String){ _name = name; } } let videoModeNormal = VideoMode() print("name:\(videoModeNormal._name)") let videoModeCustom = VideoMode(name: "Jack") print("name:\(videoModeCustom._name)") 結果: name:Jin name:Jack
當然,struct的初始化方法也是可以這樣實現的:
struct Resolution { var width: Double init(){ width = 100 } init(width:Double){ self.width = width; } } let resolutionNormal = Resolution() print("width:\(resolutionNormal.width)") let resolutionCustom = Resolution(width: 120) print("width:\(resolutionCustom.width)") 結果: width:100.0 width:120.0
類和結構體的選擇
結構體實例通過值傳遞,類實例通過引用傳遞.這意味兩者通過不同的任務,當你在考慮一個項目數據構造和功能的時候,你需要決定每個數據構造是定義成類還是結構體.
當符合一條或多條以下條件時,請考慮構建結構體:
- 結構體的主要目的是用來封裝少量相關的簡單數據值
- 有理由預計一個結構體實例在賦值或傳遞時,封裝的數據將會被拷貝而不是被引用
- 任何在結構體中儲存的值類型屬性,也會被拷貝,而不是被引用
- 結構體不需要去繼承另一個已存在類型的屬性或者行為
為什么Swift中推薦使用Struct?
Swift 里更推薦使用值類型變量(struct)而不是引用類型(class)的變量,Swift中許多常見的數據類型,字符串,集合類型以及結構體和枚舉都是值類型而非引用類型,值類型的變量在賦值時會自動進行一次低消耗的值拷貝,對比對象的copy要更加高效而且不存在線程安全的問題.
上面就是Swift中的Struct結構體.希望對大家有所幫助!!!