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不能共存