自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

站在OC的基礎(chǔ)上快速理解Swift的類與結(jié)構(gòu)體

移動開發(fā) iOS
首先我發(fā)現(xiàn)在編寫Swift代碼的時候,經(jīng)常會遇到Xcode不能提示,卡頓,直接閃退等問題,尤其是在Swift和OC混編時。(不知道其他開發(fā)者是否也有這樣的經(jīng)歷,但是我相信這樣的問題,很快會得到解決

首先我發(fā)現(xiàn)在編寫Swift代碼的時候,經(jīng)常會遇到Xcode不能提示,卡頓,直接閃退等問題,尤其是在Swift和OC混編時。(不知道其他開發(fā)者是否也有這樣的經(jīng)歷,但是我相信這樣的問題,很快會得到解決

然后感覺Swift并不像網(wǎng)上很多朋友說的那樣簡單。有很多細(xì)節(jié)問題是值得注意的,甚至有很多思路是顛覆了傳統(tǒng)的開發(fā)語言的!又有很多特性是結(jié)合了其他編程語言的優(yōu)點(diǎn)!

Swift,我個人覺得是趨勢,是目前最前衛(wèi)的開發(fā)語言,結(jié)合了眾多開發(fā)語言的優(yōu)點(diǎn)!
網(wǎng)上已經(jīng)有很多Swift相關(guān)的論文和博客了,這里我不做推薦和轉(zhuǎn)載了!我歸納一下類和結(jié)構(gòu)體,以及相關(guān)的知識吧!

Swift中,類和結(jié)構(gòu)體都是對數(shù)據(jù)和方法進(jìn)行封裝的常用做法!首先我們來看看他們的共同之處:

都可以有屬性和方法;

都有構(gòu)造器;

都支持附屬腳本;

都支持?jǐn)U展;

都支持協(xié)議。

然后我們來看看他們的不同之處:

類有繼承;

結(jié)構(gòu)體有一個自動生成的逐一初始化構(gòu)造器;

在做賦值操作時,結(jié)構(gòu)體總是被拷貝(Array有特殊處理);

結(jié)構(gòu)體可以聲明靜態(tài)的屬性和方法;

從設(shè)計(jì)模式的角度來分析,類的設(shè)計(jì)更側(cè)重于對功能的封裝,而結(jié)構(gòu)體的設(shè)計(jì)更側(cè)重于對數(shù)據(jù)的封裝。(汽車與書架來區(qū)分類與結(jié)構(gòu)體)

一、構(gòu)造過程

1. 默認(rèn)值

在OC 類和結(jié)構(gòu)的成員屬性會隱式的給出默認(rèn)值,對象的默認(rèn)值是nil,基本數(shù)據(jù)類型的默認(rèn)值是0。但是在 Swift 中屬性必須顯示的設(shè)置默認(rèn)值,Swift會在調(diào)用構(gòu)造器之前調(diào)用默認(rèn)值構(gòu)造器對所有在設(shè)置了默認(rèn)值的屬性進(jìn)行初始化。

當(dāng)一個構(gòu)造過程完成的時候,被構(gòu)造的類或者結(jié)構(gòu)體的實(shí)例的存儲屬性都會是有值的,否則編譯錯誤!

  1. class A : SuperClass { 
  2.       var _a = 1      // 默認(rèn)值 = Int(1) 
  3.       var _b: Int?    // 默認(rèn)值 = nil 
  4.       var _c: Int     // 無默認(rèn)值,必須在構(gòu)造器中賦值 
  5.       var _d: Int!    // 默認(rèn)值 = nil 
  6.       init() { 
  7.           _c = 1      // 在調(diào)用父類的構(gòu)造器之前,必須給_c賦值,否則編譯錯誤 
  8.           super.init() 
  9.       } 
  10.       ... 
  11.   } 

2. 構(gòu)造器

類似與OC的 -(instance)init 方法。和OC***的區(qū)別是 OC 初始化完成后返回的是這個對象的指針,而Swift初始化完成后返回的是這個對象的引用。

根據(jù)構(gòu)造器的實(shí)際構(gòu)造過程可將構(gòu)造器分為 便利構(gòu)造器 和 指定構(gòu)造器,但只有指定構(gòu)造器才是真實(shí)的構(gòu)造器,便利構(gòu)造器只是為指定構(gòu)造器添加一個便利的參數(shù)傳入,或者增加一些附加操作。

以下幾點(diǎn)在開發(fā)的時候需要注意:

類和結(jié)構(gòu)體都需要在構(gòu)造器完成對所有存儲屬性的初始化;

子類在調(diào)用父類的構(gòu)造器之前必須確保本類聲明的所有的存儲屬性都已經(jīng)有值了;

便利構(gòu)造器必須直接或者間接的調(diào)用本類的指定構(gòu)造器。

  1. class A : SomeClass { 
  2.      var _a: Int 
  3.      var _b = 1_000 
  4.      // 指定構(gòu)造器 
  5.      init() { 
  6.          self._a = 5     // 如果是這樣聲明的 'var _a: Int = 5' or 'var _a = 5',那么init()構(gòu)造器可以不寫而直接調(diào)用 
  7.          super.init() 
  8.      } 
  9.      // 指定構(gòu)造器 
  10.      init(a: Int) {       
  11.          self._a = a     // 因?yàn)?nbsp;_a 屬性沒有默認(rèn)值,所以在調(diào)用 super.init() 前必須給 _a 賦值,否則編譯錯誤! 
  12.          super.init()  
  13.      } 
  14.      // 便利構(gòu)造器 
  15.      convince init(a: Int, b: Int) { 
  16.          self.init(a: a + b)         // 直接調(diào)用指定構(gòu)造器 
  17.      } 
  18.      // 便利構(gòu)造器 
  19.      convince init(a: Int, b: Int, c: Int) { 
  20.          self.init(a: a, b: b + c)   // 間接調(diào)用指定構(gòu)造器 
  21.      }    
  22.      ... 
  23.  } 

3. 析構(gòu)器

和OC的 dealloc 很像,這里不多做解釋了。

  1. class A { 
  2.     ... 
  3.     deinit {     
  4.         //...  析構(gòu)器內(nèi)部處理 
  5.     } 
  6.     ... 

二、屬性

OC中的類有屬性,也有實(shí)例變量。但Swift中將類的實(shí)例變量和屬性統(tǒng)一用屬性來實(shí)現(xiàn)。

1. 存儲屬性

簡單來說就是一個成員變量/常量。Swift可以為存儲屬性增加屬性監(jiān)視器來響應(yīng)屬性值被設(shè)置時的變化。

  1. class SomeClass { 
  2.     let _a = 100        // 常量 
  3.     var _b: Int         // 沒有默認(rèn)值的變量 
  4.     var _c = 200        // 默認(rèn)值=200的Int變量 
  5.     var _d: Int = 200 { // 默認(rèn)值=200的Int變量,如果增加了屬性監(jiān)視器,必須顯示的聲明變量類型 
  6.         didSet { 
  7.             println("A 的 _c 屬性 didSet = old:\(oldValue) -> \(self._c)")   // oldValue 表示曾經(jīng)的值 
  8.         } 
  9.         willSet { 
  10.             println("A 的 _c 屬性 willSet = \(self._c) -> new:\(newValue)")  // newValue 表示將會被設(shè)置的值 
  11.         } 
  12.     } 

2. 計(jì)算屬性

計(jì)算屬性并不存儲任何數(shù)據(jù),他只是提供 set/get 的便利接口。

  1. class A { 
  2.     class var a: Int {  // 這是類的計(jì)算屬性 (區(qū)別于下面類的實(shí)例的計(jì)算屬性) 
  3.         return 1001 
  4.     } 
  5.     private(set) var _b = 100   // 外部可以訪問,但不能修改 
  6.     private var _a = 100        // 私有變量,外部不能訪問 
  7.     var a: Int {                // 只讀計(jì)算屬性 
  8.         return _a 
  9.     } 
  10.     var b: Int {                // 可讀可寫的計(jì)算屬性 
  11.         get { 
  12.             retrun _a 
  13.         } 
  14.         set { 
  15.             _a = newValue       // newValue 表示的是輸入的值 
  16.         } 
  17.     } 

3. 延遲存儲屬性

相信大家都聽說過延遲加載(懶加載),就是為了避免一些無謂的性能開銷,在真正需要該數(shù)據(jù)的時候,才真正執(zhí)行數(shù)據(jù)加載操作。 Swift可以使用關(guān)鍵字 lazy 來聲明延遲存儲屬性,延遲存儲屬性在默認(rèn)值構(gòu)造器中不會被初始化,而是在***次使用前進(jìn)行初始化! 雖然沒被初始化,但是編譯器會認(rèn)為他是有值的。

全局的常量或者變量都是延遲加載的, 包括結(jié)構(gòu)體的靜態(tài)屬性也是延遲加載的。

  1. let some = A() 
  2. class A { 
  3.     lazy var view = UIView(frame: CGRectZero) // 定義了一個延遲存儲屬性      ... 

4. 靜態(tài)屬性

結(jié)構(gòu)體可以使用關(guān)鍵字 static 來聲明靜態(tài)存儲屬性。(枚舉也可以有) Swift的類不支持靜態(tài)屬性,也不支持靜態(tài)臨時變量。 這可以作為Swift中聲明單例的一種實(shí)現(xiàn)方:

  1. class Tools { 
  2.     class func sharedInstance() -> Tools { 
  3.         struct Static { 
  4.             static let sharedInstance = QNTools() 
  5.         } 
  6.         return Static.sharedInstance 
  7.     } 

三、方法

Swift的類和結(jié)構(gòu)體都可以定義自己的方法!(OC的結(jié)構(gòu)體是沒有方法的)

1. 參數(shù)

一個方法的參數(shù)有局部參數(shù)名稱和外部參數(shù)名稱,一樣時寫一個即可! Swift的方法的參數(shù)非常靈活,可以是值,可以是引用,可以是閉包,可以是元組... Swift的方法的返回值跟參數(shù)一樣靈活

這里給出一個簡單的加法方法來展示方法的參數(shù):

  1. class A { 
  2.     // eg. 一個簡單的相加方法 
  3.     // 完整版 
  4.     class func sum1(let a/*外部參數(shù)名稱*/ aValue/*內(nèi)部參數(shù)名稱*/: Int, let b/*外部參數(shù)名稱*/ bValue/*內(nèi)部參數(shù)名稱*/: Int) -> Int { 
  5.         return aValue + bValue 
  6.     } 
  7.     // 當(dāng)函數(shù)參數(shù)的外部和內(nèi)部參數(shù)相同的時候,可以只寫一個,  此時***個參數(shù)的名稱在調(diào)用時是隱藏的 
  8.     class func sum2(a: Int, b: Int) -> Int { 
  9.         return a + b 
  10.     } 
  11.     // 使用 _ 符號,可以在調(diào)用的時候隱藏函數(shù)參數(shù)名稱,***個參數(shù)默認(rèn)就是隱藏的 
  12.     class func sum3(a: Int, _ b: Int) -> Int { 
  13.         // 內(nèi)嵌函數(shù)的參數(shù)名稱,都是可以隱藏的。而不用使用 _ 符號聲明 
  14.         func sum4(a: Int, b: Int) -> Int { 
  15.             return a + b 
  16.         } 
  17.         return sum4(a, b) 
  18.     } 
  19.     // 可使用 let/var 關(guān)鍵字來聲明參數(shù)是作為常量還是變量被傳入,(如果是常量,可以不用顯示的寫 let) 
  20.     class func sum4(let a: Int, _ b: Int) -> Int { 
  21.         // 內(nèi)嵌函數(shù)的參數(shù)名稱,都是可以隱藏的。而不用使用 _ 符號聲明 
  22.         func sum4(a: Int, b: Int) -> Int { 
  23.             return a + b 
  24.         } 
  25.         return sum4(a, b) 
  26.     } 
  27.     // 可使用 let/var 關(guān)鍵字來聲明參數(shù)是作為常量還是變量被傳入,(如果是常量,可以不用顯示的寫 let) 
  28.     class func sum5(let a: Int, let _ b: Int) -> Int { 
  29.         // 內(nèi)嵌函數(shù)的參數(shù)名稱,都是可以隱藏的。而不用使用 _ 符號聲明 
  30.         return a + b 
  31.     } 
  32.     class func sum6(var a: Int, var _ b: Int) -> Int { 
  33.         // 內(nèi)嵌函數(shù)的參數(shù)名稱,都是可以隱藏的。而不用使用 _ 符號聲明 
  34.         a++ 
  35.         b++ 
  36.         return a + b 
  37.     } 
  38.     // 可使用 inout 關(guān)鍵字,傳引用 
  39.     class func add(inout value: Int) { 
  40.         value++ 
  41.     } 
  42. }
  1. A.sum1(a: 1, b: 2)          // result: 3 
  2. A.sum2(1, b: 2)             // result: 3 
  3. A.sum3(12)                // result: 3 
  4. var aTemp: Int = 1001       // aTemp = 1001 
  5. A.add(&aTemp) 
  6. aTemp                       // aTemp = 1002 
  7. A.sum5(12)               // result: 3 
  8. A.sum6(12)               // result: 5 

2. 實(shí)例方法

類或者結(jié)構(gòu)體的實(shí)例所擁有的方法!

  1. class A { 
  2.     private(set) var a: Int = 100 
  3.     func reset() -> Void { 
  4.         self.a = 100 
  5.     } 
  6. struct S { 
  7.     var a: Int = 100 
  8.     mutating func reset() -> Void { // 注意: 在結(jié)構(gòu)體和枚舉的實(shí)例方法中如果需要修改屬性,則需要增加 mutating 字段 
  9.         self.a = 100 
  10.     } 

3. 類方法

Swift 中類的本身也是一個實(shí)例。他沒有存儲屬性、但擁有計(jì)算屬性和方法!

參考 “1.參數(shù)” 中的示例

4. 靜態(tài)方法

結(jié)構(gòu)體可以使用關(guān)鍵字 static 來聲明靜態(tài)方法。

  1. struct S { 
  2.     static func name() -> String { 
  3.         return "Liuyu" 
  4.     } 

四、附屬腳本

Swift 提供了附屬腳本的語法來簡化類似查詢的行為。如訪問一個數(shù)組的第n個元素,array[n], 訪問一個字典的值 dictionary[“key”],這些都可以通過附屬腳本來實(shí)現(xiàn)。 這里給出一個通過字符串類型的索引來查詢數(shù)組中的元素的例子。

  1. // 擴(kuò)展一個通過字符串類型的位置來訪問數(shù)據(jù)的附屬腳本 
  2. extension Array { 
  3.     subscript(index: String) -> T? { 
  4.         if let iIndex = index.toInt() { 
  5.             return self[iIndex] 
  6.         } 
  7.         return nil 
  8.     } 
  9. let array = ["Liu0""Liu1""Liu2"
  10. array[1]    // result : Liu1 
  11. array["1"]! // result : Liu1 

五、繼承

和OC一樣,Swift類可以通過繼承來獲取父類的屬性和方法(有限制)。 Swift的類的在繼承上增加了很多安全措施

  1. class SomeSuperClass { 
  2.     func someFunc1() { 
  3.         ... 
  4.     } 
  5.     // 定義不能被子類重寫的方法,需要加上 final 關(guān)鍵字 
  6.     final func someFunc2() { 
  7.         ... 
  8.     }  
  9. class SomeClass : SomeSuperClass { 
  10.     // 重載父類的方法,需要加上 override 關(guān)鍵字 
  11.     override func someFunc1() { 
  12.         ... 
  13.         super.someFunc1() 
  14.     } 
  15.     // 不能被子類重寫的方法 
  16.     override func someFunc2() {     // Error 
  17.         ... 
  18.         super.someFunc2() 
  19.     } 

六、擴(kuò)展

擴(kuò)展就是向一個已有的類、結(jié)構(gòu)體或枚舉類型添加新功能。 這包括在沒有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的能力(即逆向建模)。 擴(kuò)展和OC中的類別(categories)類似,但又有很多細(xì)微的區(qū)別:

擴(kuò)展沒有名字,一旦擴(kuò)展就會應(yīng)用到整個工程(模塊)

在擴(kuò)展中如果要重載現(xiàn)有的方法,需加上override關(guān)鍵字 (不建議修改現(xiàn)有的方法)

可定義新的嵌套類型

這里給出一個數(shù)學(xué)項(xiàng)目中計(jì)算距離時的一個擴(kuò)展

  1. typealias Distance = Double 
  2. extension Distance { 
  3.     var km: Double { return self/1_000.0 } 
  4.     var m : Double { return self } 
  5.     var cm: Double { return self*100.0 } 
  6.     var mm: Double { return self*1_000.0 } 
  7. let distance = Distance(1000)   // 1000m的距離 
  8. distance.km     // result : 1.0     (km) 
  9. distance.m      // result : 1000.0  (m) 
  10. distance.cm     // result : 100.0   (cm) 

 

責(zé)任編輯:chenqingxiang
相關(guān)推薦

2009-03-13 10:19:00

2013-10-08 09:56:20

WindowsChrome OS

2021-04-20 09:00:48

Go 語言結(jié)構(gòu)體type

2012-01-05 10:14:09

云計(jì)算蘋果

2020-12-02 09:10:22

Go結(jié)構(gòu)數(shù)據(jù)類型

2024-10-16 09:57:52

空結(jié)構(gòu)體map屬性

2009-08-13 14:06:37

C#結(jié)構(gòu)體結(jié)構(gòu)體和類的區(qū)別

2014-09-02 16:45:50

2011-07-06 14:12:14

Objective-C

2011-03-31 13:13:24

編程

2018-06-03 09:26:58

云計(jì)算數(shù)據(jù)技術(shù)層

2023-02-03 09:52:10

開發(fā)者框架GoFrame

2021-07-16 04:57:45

Go算法結(jié)構(gòu)

2022-05-07 08:00:37

Span數(shù)據(jù)結(jié)構(gòu)內(nèi)存

2009-04-07 18:57:45

Vmware虛擬化云計(jì)算

2009-08-27 16:18:47

C#類C#結(jié)構(gòu)體

2010-02-25 17:56:39

Linux操作系統(tǒng)

2015-07-20 15:44:46

Swift框架MJExtension反射

2015-06-04 17:26:26

2020-11-23 08:54:14

Go語言結(jié)構(gòu)體
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號