Swift文件Chapter 10 屬性
屬性將值與特定的類,結構體或者列舉關聯。屬性分為:
- 儲存屬性,將常量和變數儲存成為例項的一部分,可以用於類和結構體;
- 計算屬性,直接計算值,可以用於類,結構體和列舉。
儲存屬性
儲存屬性是儲存在特定類或者結構體例項裡的變數或者常量。變數使用var
定義,常量使用let
定義。
常量結構體的儲存屬性
定義為常量的結構體中的儲存屬性在第一次賦值後不可以修改,即使結構體內部宣告成了變數,因為結構體是值型別。
類即使宣告成常量,內部的變數儲存屬性依然可以更改,因為類是引用型別。
延遲載入儲存屬性
延遲載入儲存屬性是隻有在第一次呼叫的時候才會計算初始值的屬性。在屬性宣告前加上lazy
表示延時載入儲存屬性。
延時載入儲存屬性必須用var
當屬性的值依賴於外部因素或者外部因素在構造結束才能知道時,或者屬性計算非常的耗時的時候,適合使用延遲載入儲存屬性。
如果被標記為
lazy
的屬性在沒初始化時就被多個執行緒訪問,無法保證這個屬性只被初始化一次。
計算屬性
計算屬性不直接儲存值,而是提供一個getter
和可選的setter
來間接獲取或者設定其他屬性或變數的值。以矩形的結構體作為例子:
struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct Rect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } }
簡化setter宣告
如果計算屬性沒有定義新值的引數名,預設使用newValue
作為新的引數名,簡化後如下:
struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }
簡化getter宣告
如果整個getter是一個單一的表示式,會隱式的返回這個結果,省略return
。
struct CompactRect {
var origin = Point()
var size = Size()
var center: Point {
get {
Point(x: origin.x + (size.width / 2),
y: origin.y + (size.height / 2))
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
只讀計算屬性
只有getter沒有setter的屬性稱為只讀計算屬性。可以通過點運算子訪問,但是不可以賦值。
所有的計算屬性都必須宣告為var
型別,因為他們的值是不固定的。
屬性觀察器
屬性觀察器監控和響應屬性值變化,每次屬性被設定值時都會呼叫,即使是設定和原來一樣的值。可以為延時屬性之外的屬性新增觀察器。
可以為屬性新增兩個觀察器:
willSet
在新的值被設定之前呼叫,新的值會作為引數傳入,如果不定義引數名稱,預設為newValue
;didSet
在新的值被設定之後呼叫,舊的值會作為引數傳入,如果不命名預設為oldValue
,如果在didSet
方法中再次對該屬性賦值,那麼新值會覆蓋舊的值。
全域性變數和區域性變數
全域性變數是在函式,方法,閉包或任何型別之外定義的變數,區域性變數是在函式、方法或閉包內部定義的變數。
全域性變數總是延遲計算的,只不過不需要lazy
的標註。區域性範圍的常量和變數從不延遲計算。
型別屬性
型別屬性不論建立多少份例項,這個屬性只有一份。類似於C語言的靜態屬性。儲存型型別屬性可以是變數或者常量,計算型型別屬性必須是變數。
型別屬性定義
使用static
關鍵字定義型別屬性。在類中定義計算型型別屬性的時候,可以使用class
關鍵字支援子類對父類的重寫。
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 1
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 6
}
}
class SomeClass {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
return 27
}
class var overrideableComputedTypeProperty: Int {
return 107
}
}
型別屬性的獲取
型別屬性的獲取也是通過點運算子訪問。但是不是通過例項訪問,而是直接通過型別訪問。