Properties
屬性作為一種組織的成員诺核,在 Swift
中可容納其的組織范圍被擴(kuò)充為類、結(jié)構(gòu)體若专、枚舉许蓖、協(xié)議。得益于Swift的構(gòu)建方式调衰,可以說(shuō)任何類型都可以有屬性膊爪。
基本概念
struct Cat {
let age: String
let color: String
}
// Cat 擁有兩個(gè)屬性,age 窖式、color蚁飒,這意味著每一個(gè)Cat的實(shí)例都會(huì)擁有它們。
關(guān)于屬性萝喘,有兩個(gè)類型:
-
存儲(chǔ)型屬性
stored properties
實(shí)例會(huì)存儲(chǔ)屬性值淮逻,有內(nèi)存開(kāi)銷琼懊。// eg.: struct Person { var fullName: String var email: String } //初始化屬性值,要知道Swift會(huì)根據(jù)結(jié)構(gòu)體的屬性自動(dòng)創(chuàng)建構(gòu)造方法爬早。 var person = Person(fullName: "Grace Murray",email: "grace@126.com") //訪問(wèn)屬性 let name = person.fullName // Grace Murray let email = person.email // grace@126.com //Grace女士 嫁給了 Hopper先生 person.fullName = "Grace Hopper" //修改屬性值 let grace = person.fullName // Grace Hopper //---- 類型聲明 //如果你不希望外部修改屬性email哼丈,可以修改結(jié)構(gòu)體中email的類型為let. struct Person { var fullName: String let email: String } //---- 默認(rèn)值 //如果希望給某個(gè)屬性設(shè)置默認(rèn)值,可以聲明時(shí)賦予筛严。 struct Person { var fullName: String var email: String var country = "China" } /* 注意醉旦,Swift 自動(dòng)創(chuàng)建的構(gòu)造方法并不會(huì)考慮是否有默認(rèn)值,所以生成實(shí)例的方法還是一樣的桨啃。 country 依然需要指定值 */ var person = Person(fullName: "Grace Murray",email: "grace@126.com" country: "China")
-
計(jì)算型屬性
computed properties
實(shí)例不會(huì)存儲(chǔ)屬性值车胡,無(wú)內(nèi)存開(kāi)銷。struct TV { var height: Double var width: Double //計(jì)算型屬性照瘾,可以是常量或變量 var diagonal: Int { let result = (height * height + width * width).squareRoot().rounded() return Int(result) } }
從上面的示例中可以看到匈棘,diagonal
屬性值其實(shí)是關(guān)聯(lián)了 height
、 width
兩個(gè)屬性值計(jì)算而來(lái)析命,而且其并沒(méi)有存儲(chǔ)任何值主卫。
進(jìn)一步來(lái)講,計(jì)算型屬性的狀態(tài)是與其它屬性相關(guān)的鹃愤。
存取方法 (Getter and setter)
上面的例子中計(jì)算型屬性 diagonal
可以被稱為read-only(只讀的)簇搅。其中的代碼塊叫做getter(取)软吐,當(dāng)然我們也可以創(chuàng)建一個(gè)可讀瘩将、可寫的計(jì)算型屬性。他會(huì)包含兩個(gè)方法关噪,setter(存) 鸟蟹、getter(取)使兔。
var diagonal: Int {
//取
get {
let result = (height * height + width * width).squareRoot().rounded()
return Int(result)
}
//存
set {
//定義 16:9
let ratioWidth = 16.0
let ratioHeight = 9.0
let ratioDiagonal =
(ratioWidth * ratioWidth + ratioHeight * ratioHeight).squareRoot()
//注意setter方法,這里間接影響了height藤韵、width 屬性值虐沥。
height = Double(newValue) * ratioHeight / ratioDiagonal
width = height * ratioWidth / ratioHeight
}
}
相對(duì)來(lái)說(shuō),存取方法對(duì)計(jì)算型屬性具有更大的意義泽艘。你可以在適當(dāng)暴露出一個(gè)計(jì)算型屬性欲险,然后通過(guò)它去影響一個(gè)實(shí)例的其它屬性或狀態(tài)。
類型屬性 (Type properties)
之前講到的屬性匹涮,是歸屬于類型實(shí)例(Instance)的天试。事實(shí)上類型也是可以擁有屬性的,那么如果我們想定義一個(gè)歸屬于類型(Type)的屬性然低,該怎樣做呢喜每?
//需要用到的關(guān)鍵詞 static
struct BasketBall {
//類型屬性
static var made = "China"
//實(shí)例屬性
var owner: String
let color: String
//計(jì)算性屬性
var description {
return owner + "favorite" + color
}
}
- 調(diào)用類型屬性
//通過(guò)類型名調(diào)用
let placeOfProduction = BasketBall.description //China
使用類型屬性务唐,意味著你可以在任意的地方訪問(wèn)存儲(chǔ)在類型中的屬性值,而無(wú)需生成實(shí)例带兜。
屬性觀察者 (Property observers)
Swift提供了觀察屬性值改變的方法枫笛,被稱為屬性觀察者。
常用的有 didSet
刚照、willSet
刑巧,但需要特別注意的是這兩個(gè)方法只對(duì)存儲(chǔ)型變量有效。
-
willSet
observer 在屬性改變時(shí)觸發(fā) -
didSet
observer 在屬性改變后觸發(fā)
struct Level {
//類型屬性
static var highestLevel = 1
//實(shí)例屬性
let id: Int
var boss: String
var unlocked: Bool {
//注意无畔,和setter 啊楚、getter方法很像,但不是一回事
didSet {
//可以訪問(wèn)其它屬性
if unlocked && id > Level.highestLevel {
Level.highestLevel = id
}
}
}
}
Tip:在屬性初始化期間浑彰,是不會(huì)觸發(fā)觀察者方法的特幔。它們只會(huì)在為一個(gè)完全初始化的實(shí)例,賦新值的時(shí)候觸發(fā)闸昨。
- 限制變量
struct LightBulb {
static let maxCurrent = 40
var current = 0 {
didSet {
if current > LightBulb.maxCurrent {
print("too hight")
//oldValue 方法內(nèi)部隱藏的舊值
//newValue 方法內(nèi)部隱藏的新值
current = oldValue
}
}
}
}
懶加載 (Lazy properties)
屬性懶加載提供了一種節(jié)省內(nèi)存和提升效率的新方式蚯斯,注意適用于存儲(chǔ)型屬性且被聲明為變量 var
。
- 語(yǔ)法
Struct Circle {
//關(guān)鍵字 lazy 閉包形式饵较,代碼塊只會(huì)執(zhí)行一次
//這里 pi 是一個(gè)存儲(chǔ)型屬性
lazy var pi = {
return ((4.0 * atan(1.0 / 5.0)) - atan(1.0 / 239.0)) * 4.0
}()
var radius = 0.0
//計(jì)算型屬性
//mutating 用來(lái)標(biāo)記對(duì)結(jié)構(gòu)體的更改
var circumference : Double {
mutating get {
return pi * radius * 2
}
}
init(radius: Double) {
self.radius = radius
}
}
/*
應(yīng)當(dāng)注意拍嵌,懶加載適用于 var 變量,雖然它的代碼塊只會(huì)運(yùn)行一次循诉。
但是横辆,在最初它是處于無(wú)值狀態(tài)的。
只有在第一次使用時(shí)茄猫,才會(huì)被初始化狈蚤。
*/
Tip:懶加載對(duì)象,存儲(chǔ)型屬性且被聲明為為變量划纽。