天天看點

iOS開發Swift篇—(九)屬性

iOS開發Swift篇—(九)屬性

一、類的定義

Swift與Objective-C定義類的差別

Objective-C:一般需要2個檔案,1個.h聲明檔案和1個.m實作檔案

Swift:隻需要1個.swift檔案

Swift中類的定義格式

1 class 類名  {
2     // ... 屬性和方法
3 }      

二、屬性

1.什麼是屬性

  Swift中的屬性(Properties),就類似于其他面向對象語言中的成員變量

2.屬性的分類

按照官方文檔的說明,屬性可以分為以下幾種

(1)存儲屬性(Stored Properties)

(2)計算屬性(Computed Properties)

(3)類型屬性(Type Properties)

3.存儲屬性

1)簡單說明

存儲屬性:存儲屬性就是存儲在對象(執行個體)中的一個變量或者常量

存儲屬性類似于其他面向對象語言中的成員變量

1 class Person {
2     var age: Int = 1
3     var height: Double = 0.0
4     let life = 1
5 }      

說明:

Person類中定義了3個存儲屬性

2個變量存儲屬性:Int類型的age、Double類型的height 

1個常量存儲屬性:Int類型的life

系統并不會自動初始化上面的3個存儲屬性,需要進行手動初始化

2)存儲屬性的讀寫

  如何讀寫存儲屬性?

  直接通過點運算符(.),就可以讀寫某個對象的存儲屬性  

1 class Person {
2     var age: Int = 1
3     let life = 1
4 }
5 var p = Person()
6 p.age = 20
7 println("p的生命是\(p.life), p的年齡是\(p.age)")      

第5行:建立Person對象

第6行:給對象p的age屬性指派

第7行:通路對象p的life屬性值和age屬性值

3)延遲存儲屬性

什麼是延遲存儲屬性?

延遲存儲屬性是第一次使用時才進行初始化的屬性

使用@lazy來辨別一個延遲存儲屬性

1 class Person {
2     @lazy var dog: Dog = Dog()
3 }
4 var p = Person()
5 println(p.dog)      

  執行第5行代碼時,才會去初始化dog屬性,才真正建立了Dog對象

延遲存儲屬性的使用注意:延遲存儲屬性必須是變量,不能是常量

延遲存儲屬性的好處:讓某些資源用到時再去加載,避免一些不必要的資源浪費

4.計算屬性

(1)什麼是計算屬性

跟存儲屬性不一樣的是,計算屬性不是直接存儲值,而是提供get和set

get:用來取值,封裝取值的過程

set:用來設值,封裝設值的過程

(2)代碼示例:

1 class Square {
 2     // 正方形的寬度
 3       var width: Double = 0.0
 4     // 正方形的周長
 5       var girth: Double {
 6         get {
 7             // 周長 = 寬度 * 4
 8                 return width * 4
 9         }
10         set(newGirth) {
11             // 寬度 = 周長 / 4
12                    width = newGirth / 4
13         }
14     }
15 }      

計算屬性舉例:

1 var s = Square()
2 s.width = 10
3 println(s.girth)
4 s.girth = 200 
5 println(s.width)       

第3行代碼:調用girth屬性的get,輸出結果是40

第4行代碼:調用girth屬性的set,并且把200傳遞給newGirth參數

第5行代碼:輸出結果是50

(3)簡便的set

  set也可以不特意指定新值的參數名,新值的預設參數名叫做newValue

1 var girth: Double {
2     get {
3         return width * 4
4     }
5     set {
6         width = newValue / 4
7     }
8 }
9 s.girth = 200       

  執行第9行代碼時:第6行中newValue的值就是200

(4)計算屬性的使用注意

  1)因為計算屬性的值不是固定的,是以隻能用var修飾計算屬性,不能用let

1 class Square {
 2     var girth: Double {
 3         get {
 4             return girth
 5         }
 6         set(newGirth) {
 7             girth = newGirth
 8         }
 9     }
10 }      

說明:上面的代碼會引發死循環,第4行代碼會引發循環調用get,第7行代碼會引發循環調用set。

2)一個屬性不能既是存儲屬性,又是計算屬性

1 class Square {
 2     var girth: Double = 20.0 {
 3         get {
 4             return 10.0
 5         }
 6         set() {
 7             
 8         }
 9     }
10 }      

說明:上面的代碼是錯誤的

(5)隻讀計算屬性

什麼是隻讀計算屬性?隻提供get,沒有set的計算屬性

1 class Square {
 2     var width: Double = 0.0
 3     var girth: Double {
 4         get {
 5             return width * 4
 6         }
 7     }
 8 }
 9 var s = Square()
10 s.girth = 200       

說明:第10行代碼會報錯

  隻讀計算屬性的簡寫。隻讀計算屬性可以省略get關鍵字

1 class Square {
2     var width: Double = 0.0
3     var girth: Double {
4         return width * 4
5     }
6 }
7 var s = Square()
8 s.girth = 200       

說明:第8行代碼會報錯

5.類型屬性

(1)什麼是類型屬性?

用class關鍵字修飾的屬性,就是類型屬性,也可以稱為“類屬性”

class修飾的類型屬性隻能是計算屬性,不能是存儲屬性

代碼示例:

1 class Circle {
2     class var PI : Double  {
3         return 3.14
4     }
5 }      

說明:第2行定義的屬性PI,就是一個類型屬性

(2)類型屬性的特點

  一個類隻會有一份,類的多個執行個體對象都共享這唯一的一份

  類型屬性的使用:類型屬性不依賴于對象而存在,是以用類名來通路

  println(Circle.PI)

三、屬性螢幕

1.什麼是屬性螢幕?

有時,需要在屬性值被修改的時候做出響應,這種情況下就可以用屬性螢幕

屬性螢幕,可以監視屬性值的修改過程 

  計算屬性可以直接在set中監聽屬性值的改變,而存儲屬性沒有set

可以為存儲屬性添加willSet和didSet兩個屬性螢幕

(1)willSet:

在設定新的屬性值之前調用

會将新的屬性值作為參數傳入,參數名預設是newValue

(2)didSet:

在設定新的屬性值之後調用

會将舊的屬性值作為參數傳入,參數明預設是oldValue

2.代碼示例

1 class Square {
 2     var width: Double = 0.0 {
 3         willSet {
 4             println("willSet---\(newValue)")
 5         }
 6         didSet {
 7             println("didSet---\(oldValue)")
 8         }
 9     }
10 }
11 var s = Square()
12 s.width = 10      

列印結果:

willSet---10.0

didSet---0.0

3.使用注意

1 class Square {
2     var width: Double = 0.0 {
3         willSet { }
4         didSet { width = 20 }
5     }
6 }
7 var s = Square()
8 s.width = 10
9 println(s.width)      

代碼說明:

willSet和didSet在屬性初始化過程中不會被調用,隻會當屬性的值在初始化之外的地方被設定時被調用

第2行代碼的初始化不會引發willSet和didSet的調用

第8行代碼的指派會引發willSet和didSet的調用

如果在didSet螢幕裡為屬性指派,這個值會替換之前設定的值

第4行對width屬性進行了再次指派,覆寫了第8行賦的值,是以第9行的輸出結果是20

willSet、didSet和set、get不能共存