Swift 屬性
Swift 屬性將值跟特定的類、結(jié)構(gòu)或枚舉關(guān)聯(lián)。
屬性可分為存儲(chǔ)屬性和計(jì)算屬性:
存儲(chǔ)屬性 | 計(jì)算屬性 |
---|---|
存儲(chǔ)常量或變量作為實(shí)例的一部分 | 計(jì)算(而不是存儲(chǔ))一個(gè)值 |
用于類和結(jié)構(gòu)體 | 用于類、結(jié)構(gòu)體和枚舉 |
存儲(chǔ)屬性和計(jì)算屬性通常用于特定類型的實(shí)例。
屬性也可以直接用于類型本身,這種屬性稱為類型屬性。
另外,還可以定義屬性觀察器來監(jiān)控屬性值的變化,以此來觸發(fā)一個(gè)自定義的操作。屬性觀察器可以添加到自己寫的存儲(chǔ)屬性上,也可以添加到從父類繼承的屬性上。
存儲(chǔ)屬性
簡單來說,一個(gè)存儲(chǔ)屬性就是存儲(chǔ)在特定類或結(jié)構(gòu)體的實(shí)例里的一個(gè)常量或變量。
存儲(chǔ)屬性可以是變量存儲(chǔ)屬性(用關(guān)鍵字var定義),也可以是常量存儲(chǔ)屬性(用關(guān)鍵字let定義)。
可以在定義存儲(chǔ)屬性的時(shí)候指定默認(rèn)值
也可以在構(gòu)造過程中設(shè)置或修改存儲(chǔ)屬性的值,甚至修改常量存儲(chǔ)屬性的值
import Cocoa struct Number { var digits: Int let pi = 3.1415 } var n = Number(digits: 12345) n.digits = 67 print("\(n.digits)") print("\(n.pi)")
以上程序執(zhí)行輸出結(jié)果為:
67 3.1415
考慮以下代碼:
let pi = 3.1415
代碼中 pi 在定義存儲(chǔ)屬性的時(shí)候指定默認(rèn)值(pi = 3.1415),所以不管你什么時(shí)候?qū)嵗Y(jié)構(gòu)體,它都不會(huì)改變。
如果你定義的是一個(gè)常量存儲(chǔ)屬性,如果嘗試修改它就會(huì)報(bào)錯(cuò),如下所示:
import Cocoa struct Number { var digits: Int let numbers = 3.1415 } var n = Number(digits: 12345) n.digits = 67 print("\(n.digits)") print("\(n.numbers)") n.numbers = 8.7
以上程序,執(zhí)行會(huì)報(bào)錯(cuò),錯(cuò)誤如下所示:
error: cannot assign to property: 'numbers' is a 'let' constant n.numbers = 8.7
意思為 'numbers' 是一個(gè)常量,你不能修改它。
延遲存儲(chǔ)屬性
延遲存儲(chǔ)屬性是指當(dāng)?shù)谝淮伪徽{(diào)用的時(shí)候才會(huì)計(jì)算其初始值的屬性。
在屬性聲明前使用 lazy 來標(biāo)示一個(gè)延遲存儲(chǔ)屬性。
注意:
必須將延遲存儲(chǔ)屬性聲明成變量(使用var
關(guān)鍵字),因?yàn)閷傩缘闹翟趯?shí)例構(gòu)造完成之前可能無法得到。而常量屬性在構(gòu)造過程完成之前必須要有初始值,因此無法聲明成延遲屬性。
延遲存儲(chǔ)屬性一般用于:
延遲對(duì)象的創(chuàng)建。
當(dāng)屬性的值依賴于其他未知類
import Cocoa class sample { lazy var no = number() // `var` 關(guān)鍵字是必須的 } class number { var name = "W3CSchool Swift 教程" } var firstsample = sample() print(firstsample.no.name)
以上程序執(zhí)行輸出結(jié)果為:
W3CSchool Swift 教程
實(shí)例化變量
如果您有過 Objective-C 經(jīng)驗(yàn),應(yīng)該知道Objective-C 為類實(shí)例存儲(chǔ)值和引用提供兩種方法。對(duì)于屬性來說,也可以使用實(shí)例變量作為屬性值的后端存儲(chǔ)。
Swift 編程語言中把這些理論統(tǒng)一用屬性來實(shí)現(xiàn)。Swift 中的屬性沒有對(duì)應(yīng)的實(shí)例變量,屬性的后端存儲(chǔ)也無法直接訪問。這就避免了不同場景下訪問方式的困擾,同時(shí)也將屬性的定義簡化成一個(gè)語句。
一個(gè)類型中屬性的全部信息——包括命名、類型和內(nèi)存管理特征——都在唯一一個(gè)地方(類型定義中)定義。
計(jì)算屬性
除存儲(chǔ)屬性外,類、結(jié)構(gòu)體和枚舉可以定義計(jì)算屬性,計(jì)算屬性不直接存儲(chǔ)值,而是提供一個(gè) getter 來獲取值,一個(gè)可選的 setter 來間接設(shè)置其他屬性或變量的值。
import Cocoa class sample { var no1 = 0.0, no2 = 0.0 var length = 300.0, breadth = 150.0 var middle: (Double, Double) { get{ return (length / 2, breadth / 2) } set(axis){ no1 = axis.0 - (length / 2) no2 = axis.1 - (breadth / 2) } } } var result = sample() print(result.middle) result.middle = (0.0, 10.0) print(result.no1) print(result.no2)
以上程序執(zhí)行輸出結(jié)果為:
(150.0, 75.0) -150.0 -65.0
如果計(jì)算屬性的 setter 沒有定義表示新值的參數(shù)名,則可以使用默認(rèn)名稱 newValue。
只讀計(jì)算屬性
只有 getter 沒有 setter 的計(jì)算屬性就是只讀計(jì)算屬性。
只讀計(jì)算屬性總是返回一個(gè)值,可以通過點(diǎn)(.)運(yùn)算符訪問,但不能設(shè)置新的值。
import Cocoa class film { var head = "" var duration = 0.0 var metaInfo: [String:String] { return [ "head": self.head, "duration":"\(self.duration)" ] } } var movie = film() movie.head = "Swift 屬性" movie.duration = 3.09 print(movie.metaInfo["head"]!) print(movie.metaInfo["duration"]!)
以上程序執(zhí)行輸出結(jié)果為:
Swift 屬性 3.09
注意:
必須使用
var
關(guān)鍵字定義計(jì)算屬性,包括只讀計(jì)算屬性,因?yàn)樗鼈兊闹挡皇枪潭ǖ摹?code>let關(guān)鍵字只用來聲明常量屬性,表示初始化后再也無法修改的值。
屬性觀察器
屬性觀察器監(jiān)控和響應(yīng)屬性值的變化,每次屬性被設(shè)置值的時(shí)候都會(huì)調(diào)用屬性觀察器,甚至新的值和現(xiàn)在的值相同的時(shí)候也不例外。
可以為除了延遲存儲(chǔ)屬性之外的其他存儲(chǔ)屬性添加屬性觀察器,也可以通過重載屬性的方式為繼承的屬性(包括存儲(chǔ)屬性和計(jì)算屬性)添加屬性觀察器。
注意:
不需要為無法重載的計(jì)算屬性添加屬性觀察器,因?yàn)榭梢酝ㄟ^ setter 直接監(jiān)控和響應(yīng)值的變化。
可以為屬性添加如下的一個(gè)或全部觀察器:
willSet
在設(shè)置新的值之前調(diào)用didSet
在新的值被設(shè)置之后立即調(diào)用- willSet和didSet觀察器在屬性初始化過程中不會(huì)被調(diào)用
import Cocoa class Samplepgm { var counter: Int = 0{ willSet(newTotal){ print("計(jì)數(shù)器: \(newTotal)") } didSet{ if counter > oldValue { print("新增數(shù) \(counter - oldValue)") } } } } let NewCounter = Samplepgm() NewCounter.counter = 100 NewCounter.counter = 800
以上程序執(zhí)行輸出結(jié)果為:
計(jì)數(shù)器: 100 新增數(shù) 100 計(jì)數(shù)器: 800 新增數(shù) 700
全局變量和局部變量
計(jì)算屬性和屬性觀察器所描述的模式也可以用于全局變量和局部變量。
局部變量 | 全局變量 |
---|---|
在函數(shù)、方法或閉包內(nèi)部定義的變量。 | 函數(shù)、方法、閉包或任何類型之外定義的變量。 |
用于存儲(chǔ)和檢索值。 | 用于存儲(chǔ)和檢索值。 |
存儲(chǔ)屬性用于獲取和設(shè)置值。 | 存儲(chǔ)屬性用于獲取和設(shè)置值。 |
也用于計(jì)算屬性。 | 也用于計(jì)算屬性。 |
類型屬性
類型屬性是作為類型定義的一部分寫在類型最外層的花括號(hào)({})內(nèi)。
使用關(guān)鍵字 static 來定義值類型的類型屬性,關(guān)鍵字 class 來為類定義類型屬性。
struct Structname { static var storedTypeProperty = " " static var computedTypeProperty: Int { // 這里返回一個(gè) Int 值 } } enum Enumname { static var storedTypeProperty = " " static var computedTypeProperty: Int { // 這里返回一個(gè) Int 值 } } class Classname { class var computedTypeProperty: Int { // 這里返回一個(gè) Int 值 } }
注意:
例子中的計(jì)算型類型屬性是只讀的,但也可以定義可讀可寫的計(jì)算型類型屬性,跟實(shí)例計(jì)算屬性的語法類似。
獲取和設(shè)置類型屬性的值
類似于實(shí)例的屬性,類型屬性的訪問也是通過點(diǎn)運(yùn)算符(.)來進(jìn)行。但是,類型屬性是通過類型本身來獲取和設(shè)置,而不是通過實(shí)例。實(shí)例如下:
import Cocoa struct StudMarks { static let markCount = 97 static var totalCount = 0 var InternalMarks: Int = 0 { didSet { if InternalMarks > StudMarks.markCount { InternalMarks = StudMarks.markCount } if InternalMarks > StudMarks.totalCount { StudMarks.totalCount = InternalMarks } } } } var stud1Mark1 = StudMarks() var stud1Mark2 = StudMarks() stud1Mark1.InternalMarks = 98 print(stud1Mark1.InternalMarks) stud1Mark2.InternalMarks = 87 print(stud1Mark2.InternalMarks)
以上程序執(zhí)行輸出結(jié)果為:
97 87
更多建議: