Swift 語言有兩種基本的數據類型,即類(class)和結構體(struct),class 這樣的概念你們不會陌生,而 struct 也並非什麼新的概念,在 Objective-C 和 C 中也有 struct,不過 Swift 將 struct 提高到一個更高更重要的層次,甚至 Swift Foundation 框架的 SDK,諸如 String,Array,Dictionary
都是基於 struct 實現的。swift
結構體是由一系列具備相同類型或不一樣類型的數據構成的數據集合。app
和 class 同樣,struct 也能夠定義屬性和方法,一樣 struct 也要求完整初始化,即保證初始化過程當中每個 non-optional 屬性要賦予明確的初始值。框架
結構體是值類型,而且只有在賦予變量或常量,或者被函數調用時才被賦值。函數
結構體基本結構ui
struct 結構體名 { var 或 let 字段名 = 初始化值 var 或 let 字段名: 類型 }
struct Student { var age = 0 } var stu = Student() /// struct 結構體關鍵字 /// Student 結構體名稱 /// student() 建立一個結構體變量
結構體的定義線程
定義結構體字段時能夠直接定義一個字段名,而且給字段名賦初始值。或者只定義一個字段名,不賦初始值,可是不賦初始值的字段在建立結構體變量時必須賦初始值。指針
struct Student { var name: String // 只定義一個字段名,不賦初始值 var age = 0 // 定義一個字段名,而且給字段名賦初始值 }
結構體的使用code
建立結構體變量時,結構體的字段都必須都有初始值,不然會報錯。對象
let s = Student(name: "appple", age: 8) // 建立結構體變量時初始化結構體的字段 print("\(s.name), \(s.age)") // 結構體類型變量值的調用
結構體的定義繼承
每一個字段名都賦初始值。
struct BookInfo { var id: Int = 0 // 每一個字段名都賦初始值 var name: String = "Default" var author: String = "Default" var rootType: String = "Default" }
結構體的使用
建立結構體變量時,結構體的字段都必須都有初始值,不然會報錯。
let book = BookInfo() // 建立結構體變量時再也不須要初始化結構體的字段 print("\(book.id), \(book.name), \(book.author), \(book.rootType)") // 結構體類型變量值的調用
枚舉方法的定義
struct markStruct1 { var mark1: Int = 0 var mark2: Int = 0 var mark3: Int = 0 func sum(a: Int) -> Int { // 定義方法 return (self.mark1 + self.mark2 + self.mark3) * a } }
枚舉方法的使用
let mark1 = markStruct1(mark1: 11, mark2: 22, mark3: 33) print(mark1.sum(a: 2)) // print 132
與 class 的初始化方法不一樣點
這樣對比,struct 的初始化方法比起 class 的初始化方法來講要簡單的多,由於 struct 只有指定初始化,struct 只須要保證指定初始化過程當中每一個非可選屬性都賦值,沒有複雜的初始化規則和規範,struct 相比於 class 也顯得更加簡單,更有親和力。
一旦咱們自定義了初始化器,系統自動的初始化器就不起做用了,若是還須要使用到系統提供的初始化器,在咱們自定義初始化器後就必須顯式的定義出來。
可失敗構造方法
struct markStruct2 { var mark1: Int var mark2: Int var mark3: Int init?(mark1: Int, mark2: Int, mark3: Int) { // 可失敗(failable)的構造方法 self.mark1 = mark1 self.mark2 = mark2 self.mark3 = mark3 } }
普通構造方法
struct markStruct3 { var mark1: Int var mark2: Int var mark3: Int init(mark1: Int, mark2: Int, mark3: Int) { // 普通的構造方法 self.mark1 = mark1 self.mark2 = mark2 self.mark3 = mark3 } }
使用
let mark2 = markStruct2(mark1: 11, mark2: 22, mark3: 33) print("\(mark2?.mark1 ?? 0), \(mark2?.mark2 ?? 0), \(mark2?.mark3 ?? 0)") // print 11, 22, 33 let mark3 = markStruct3(mark1: 11, mark2: 22, mark3: 33) print("\(mark3.mark1), \(mark3.mark2), \(mark3.mark3)") // print 11, 22, 33
對於類型引用(class reference),將變量 a
賦值給變量 b
,即 b = a
,這樣的賦值語句僅僅將 b
的指針與 a
的指針同樣,指向同一塊內存區域,此時改變 b
的值,a
也會跟着改變;
對於值引用(value reference),賦值語句 b = a
處理的過程是開闢一個新的內存 b
,將 a
變量的內容拷貝後存放到內存 b
,這時 a
和 b
徹底沒有關係的兩個變量,對 b
的改變不會影響到 a
,反之亦然。
在 Objective-C 時代,咱們對類型引用和值引用就有了必定的瞭解,例如在 Objective-C 中經常使用的 NSArray, NSDictionary, NSString, UIKit
等都是類型引用;而 NSInteger, CGFloat, CGRect
等則是值引用。
顯然,在 Objective-C 中,引用類型佔據了很大的比重,如今使用 Swift 開發應用程序,開發者須要轉變觀念,由於 struct 在 Swift 變得愈來愈重要,觀念的轉變不只在於多使用 struct,還要求開發者理解 struct 的原理,優勢及缺點。
關於在新建一個類型時如何選擇究竟是使用值類型仍是引用類型的問題其實在理解了二者之間的區別後是很是簡單的,在這蘋果官方已經作出了很是明確的指示
NSObject
的子類使用,因此這時候必需要用到引用類型 class。1)何時該用值類型
==
運算符來比較實例的數據時2)何時該用引用類型(class)
==
運算符來比較實例身份的時候