Swift:11 屬性
類似于Objective-C中的類成員變量和屬性,在Swift中,也有屬性的概念。類的實例和類型本身都可以有屬性,我們稱之為實例屬性和類型屬性。屬性又分為存儲屬性和計算屬性兩種,其中,類、結構和枚舉都提供了計算屬性,而只有類和結構體有存儲屬性。
存儲屬性
存儲屬性是類和結構體中用來存儲常量和變量數據的屬性。對于常量類型的存儲屬性,只能在屬性初始化的時候賦值一次,就不可以再修改了。通過前面的結構體章節介紹,我們可知,結構體是值類型的,所以,如果一個結構體是一個常量的話,那么他的變量存儲屬性也只能賦值一次。而類是引用類型,沒有這個限制。
struct size {
var width:Int
let height:Int
}
var s_var = size(width: 10, height: 20)
s_var.width = 30
//s_var.height = 40,無法編譯,常量屬性,不能被改變
let s_constant = size(width: 50, height: 60)
//d_var.width = 60,無法編譯,常量結構體所有屬性只能被初始化一次
計算屬性
除存儲屬性外,類、結構體和枚舉還可以定義計算屬性,計算屬性不直接存儲值,而是提供一個 getter 選擇器來獲取值,一個可選的 setter 設置器來間接設置其他屬性或變量的值。
struct rect {
var width:Int
let height:Int
var circumference:Int{
get{
return 2*(width+height)
}
set(circu){
width = circu/2 - height
}
}
}
var r = rect(width: 20, height: 10)
print("現在的周長是:\(r.circumference)")
//打印結果:現在的周長是:60
r.circumference = 50
print("更改后寬度是:\(r.width),周長是\(r.circumference)")
//打印結果:更改后寬度是:15,周長是50
如果計算屬性的setter沒有為新設置的值定義名稱,使用默認的名稱newValue。
var circumference:Int{
get{
return 2*(width+height)
}
set{
width = newValue/2 - height
}
}
只有getter沒有setter的計算屬性被稱為只讀計算屬性(read-only computed properties)。只讀計算屬性始終返回一個值,并且可以通過點語法訪問,但是不可以設置值。同時,get關鍵字可以直接省略。
struct rect {
var width:Int
let height:Int
var area:Int{
return width*height
}
}
var r = rect(width: 20, height: 10)
print("現在的面積是:\(r.area)")
//現在的面積是:200
屬性監視器
屬性監視器是用來監視和響應屬性值的改變,每次當屬性值被設置的時候,屬性監視器就會自動被調用。
可以為存儲屬性添加屬性監視器,也可以在子類中通過覆蓋屬性的方式來給任何繼承屬性(存儲屬性和計算屬性)來添加屬性監視器。不需要為未覆蓋過的計算屬性定義屬性監視器,因為完全可以通過setter來直接監視和響應計算屬性的值的變化。
有兩種監視器(willSet和didSet),可以選擇全部或選任意其中一個,其中willSet在值設置前調用,didSet在新的值設置后立即調用。
willSet和didSet都可以設置一個常量形參來傳遞新、舊屬性值。常量形參如果不設置,則使用默認的newValue、oldValue來傳遞。
struct gold{
var num:Int{
willSet{
if newValue < 0{
print("金幣數低于0")
}
}
didSet{
if oldValue < num{
print("金幣數增加了:\((num-oldValue))")
}
}
}
}
var my_gold = gold(num: 10)
my_gold.num = -2
my_gold.num = 0
my_gold.num = 30
代碼執行結果如下圖。
類型屬性
類型屬性,也可以叫做類屬性,就是屬于某個類型的屬性,該類型下所有的實例都共享一份值。由于類型屬性不依賴于該類型的任何實例,所以,類型屬性在定義的時候必須要設置初始值。類型屬性也有存儲屬性和計算屬性兩種。
在結構體和枚舉中定義類型屬性,使用static關鍵字,而在類中定義計算類型屬性需要使用class關鍵字。類型屬性使用點(.)運算符進行訪問和設置。
class rectClass{
static var width = 10
class var proper:Int{
return 10
}
}
enum fruits{
static var level = 3
static var totals:Int{
return 1
}
}
struct rect{
static var width = 10
var height:Int
var area:Int{
return height * rect.width
}
}
let rt = rect(height: 20)
print("rt的面積是:\(rt.area)")
rect.width = 30
print("rt的面積是:\(rt.area)")
let rt2 = rect(height: 10)
print("rt2的面積是:\(rt2.area)")
代碼執行結果如下圖。
示例代碼
https://github.com/99ios/23.12