- 屬性是將值跟特定的類怀读、結(jié)構(gòu)體或者枚舉關(guān)聯(lián)绎橘。存儲(chǔ)屬性存儲(chǔ)常量或者變量作為實(shí)例的一部分胁孙,用于類和結(jié)構(gòu)體;計(jì)算屬性是用來計(jì)算一個(gè)值称鳞,可以用在類涮较、結(jié)構(gòu)體和枚舉。
- 存儲(chǔ)屬性和計(jì)算屬性通常與特定的類型的實(shí)例關(guān)聯(lián)冈止。但是狂票,屬性也可以直接作用于類型本身,這樣的屬性成為類型屬性熙暴。
- Swift可以定義屬性觀察器來監(jiān)控屬性值的改變苫亦,屬性觀察期可以添加到自己定義的存儲(chǔ)屬性上,也可以添加到父類繼承的屬性上
1.存儲(chǔ)屬性
- 存儲(chǔ)屬性就是存儲(chǔ)在特定類怨咪、結(jié)構(gòu)體里的一個(gè)常量或者變量屋剑。
- 可以在定義存儲(chǔ)屬性的時(shí)候指定默認(rèn)值。
- 可以在構(gòu)造過程中設(shè)置或者修改存儲(chǔ)屬性的值诗眨。
// 定義一個(gè)結(jié)構(gòu)體如下唉匾,F(xiàn)ixedLengthRange代表一個(gè)創(chuàng)建后無(wú)法改變的區(qū)間
struct FixedLengthRange {
var firstValue: Int
let lenght: Int
}
var rangeOfThreeItens = FixedLengthRange(firstValue: 0, lenght: 3)
// rangeOfThreeItens 實(shí)例包括了名為firstValue的變量存儲(chǔ)屬性和lenght的常量存儲(chǔ)屬性
// 其中l(wèi)enght在創(chuàng)建后無(wú)法被修改
rangeOfThreeItens.firstValue = 7;
// rangeOfThreeItens 現(xiàn)在的表示7 8 9的區(qū)間
1.1 常量結(jié)構(gòu)體的存儲(chǔ)屬性
- 當(dāng)創(chuàng)建了一個(gè)結(jié)構(gòu)體的實(shí)例并賦值一個(gè)常量,那么無(wú)法修改該實(shí)例的任何屬性。
- 結(jié)構(gòu)體是值類型巍膘,當(dāng)值類型的實(shí)例被聲明為常量的時(shí)候厂财,它的所有屬性都變成了常量。
當(dāng)嘗試下面的修改時(shí)峡懈,就會(huì)報(bào)錯(cuò)
let rangeOfThreeItens = FixedLengthRange(firstValue: 0, lenght: 3)
rangeOfThreeItens.firstValue = 8
1.2延遲存儲(chǔ)屬性
- 延遲存儲(chǔ)屬性是指第一次被調(diào)用的時(shí)候才會(huì)計(jì)算其初始值的屬性璃饱,就是常說的懶加載。
- Swift在屬性前加lazy關(guān)鍵字來標(biāo)記一個(gè)延遲存儲(chǔ)屬性肪康,延遲存儲(chǔ)屬性必須用變量(var關(guān)鍵字)荚恶。
- 當(dāng)屬性依賴其他外部因素影響(如構(gòu)造過程,初始值復(fù)雜磷支,大量計(jì)算)谒撼,適合用延遲屬性。
// DataImporter是一個(gè)導(dǎo)入數(shù)據(jù)的類雾狈,導(dǎo)入過程會(huì)消耗大量的時(shí)間
class DataImporter {
var fileName = "data.text"
/** 導(dǎo)入數(shù)據(jù) **/
}
// DataManager用來管理和提供對(duì)這個(gè)字符串?dāng)?shù)組的訪問
class DataManager {
lazy var importer = DataImporter()
var data = [String]()
/** 管理數(shù)據(jù) **/
}
let manager = DataManager()
manager.data.append("someData")
manager.data.append("someMore")
簡(jiǎn)單描述了一個(gè)DataManager類廓潜,導(dǎo)入文件的過程。DataManager用來管理數(shù)據(jù)的導(dǎo)入善榛,依賴與DataImporter的功能辩蛋。導(dǎo)入數(shù)據(jù)消耗太多的時(shí)間,而且DataManager也可能不導(dǎo)入數(shù)據(jù)就完成了管理數(shù)據(jù)的過程移盆。DataImporter不需要立刻創(chuàng)建悼院,只有在使用的時(shí)候才去創(chuàng)建。
print(manager.importer.fileName)
只有執(zhí)行上述代碼的時(shí)候味滞,DataImporter實(shí)例才會(huì)被創(chuàng)建舶吗。
1.3存儲(chǔ)屬性和實(shí)例變量
- OC中邑商,提供了為類實(shí)例存儲(chǔ)值和引用提供了兩種方法,通過_XXXXX或者self.XXXXX.
- Swift統(tǒng)一了OC的方法铐然,屬性沒有對(duì)應(yīng)的實(shí)例變量(_XXXXX)
- 一個(gè)類型中屬性的全部信息--命名爽醋、類型蚁署、內(nèi)存管理特性,全部都在唯一的地方(類型定義中)
2.計(jì)算屬性
- 枚舉蚂四、類光戈、結(jié)構(gòu)體除了擁有存儲(chǔ)屬性,還可以定義計(jì)算屬性遂赠。
- 計(jì)算屬性不直接存儲(chǔ)值久妆,而是提供一個(gè)getter和一個(gè)可選的setter來間接獲取、設(shè)置其他屬性和變量的值跷睦。
// 下面定義三個(gè)結(jié)構(gòu)體筷弦,來描述一個(gè)矩形
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 * 0.5)
let centerY = origin.y + (size.height * 0.5)
return Point(x: centerX, y: centerY)
}
set(newCenter){
origin.x = newCenter.x - (size.width * 0.5)
origin.y = newCenter.y - (size.height * 0.5)
}
}
}
// 創(chuàng)建一個(gè)矩形
var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
// 重新設(shè)置矩形的中心點(diǎn)
let initialSquareCenter = square.center;
square.center = Point(x: 20.0, y: 20.0)
2.1便捷setter聲明
- 如果計(jì)算屬性的setter沒有定義表示新值的參數(shù)名,則可以用默認(rèn)值newValue,上述代碼可以改寫
struct Rect {
var origin = Point()
var size = Size()
var center: Point{
get{
let centerX = origin.x + (size.width * 0.5)
let centerY = origin.y + (size.height * 0.5)
return Point(x: centerX, y: centerY)
}
set{
origin.x = newValue.x - (size.width * 0.5)
origin.y = newValue.y - (size.height * 0.5)
}
}
}
2.2只讀計(jì)算屬性
- 只有g(shù)etter沒有setter的計(jì)算屬性
- 只讀計(jì)算屬性總是返回一個(gè)值,可以通過點(diǎn)語(yǔ)法訪問烂琴,但是不能設(shè)置
- 只讀計(jì)算屬性可以省略get和花括號(hào)
// 一個(gè)結(jié)構(gòu)體 爹殊,volume計(jì)算體積
struct Cuboid{
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double{
return width * height * depth
}
}
let newCuboid = Cuboid(width: 3.0, height: 4.0, depth: 5.0)
3.屬性觀察器
- 屬性觀察器監(jiān)控和響應(yīng)屬性值的變化,每次屬性被設(shè)置值的時(shí)候都會(huì)調(diào)用奸绷。
- 延遲屬性不可以設(shè)置屬性觀察器
- 可以通過重寫屬性的方式為繼承的屬性添加觀察器
- willSet : 在新的值被設(shè)置之前調(diào)用
- didSet : 在新的值被設(shè)置之后調(diào)用
- 父類的屬性在子類的構(gòu)造器被賦值時(shí)梗夸,觀察器同樣會(huì)被觸發(fā)
// StepCounter是一個(gè)計(jì)步器
class StepCounter{
var totalStep: Int = 0{
willSet(newTotalSteps){
print("現(xiàn)在總步數(shù)是\(newTotalSteps)步")
}
didSet{
if totalStep > oldValue{
print("增加了\(totalStep - oldValue)步")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalStep = 200;
// 現(xiàn)在總步數(shù)是200,增加了200步
stepCounter.totalStep = 500;
// 現(xiàn)在總步數(shù)是500,增加了300步
4.全局變量和局部變量
全局變量是在函數(shù)、方法号醉、閉包或者其他類型之外定義的變量反症。局部變量是在函數(shù)、方法扣癣、或者閉包內(nèi)定義的惰帽。
- 計(jì)算屬性和屬性觀察器所描述的模式也可以用于全局變量和局部變量。
- 默認(rèn)的全局和局部變量都是存儲(chǔ)型變量父虑,跟存儲(chǔ)屬性類似该酗,它提供存儲(chǔ)空間,并且允許讀取和寫入
- 全局和局部變量都可以定義計(jì)算屬性和添加屬性觀察器士嚎。
- 注意N仄恰!
- 全局的常量或者變量都是延遲計(jì)算的莱衩,跟延遲存儲(chǔ)屬性不同的地方在于爵嗅,全局的常量或者變量不需要標(biāo)記lazy。
- 局部范圍的常量或者變量不會(huì)延遲計(jì)算笨蚁。
5.類型屬性
實(shí)例的屬性屬于一個(gè)特定的實(shí)例睹晒,實(shí)例之間的屬性相互獨(dú)立,也可以為類型本身設(shè)置屬性括细,不管類有多少的實(shí)例伪很,這些屬性只有唯一一份,這個(gè)就是類型屬性奋单。
- 類型屬性锉试,比如所有實(shí)例都有一個(gè)常量(類似C語(yǔ)言的靜態(tài)常量),或者擁有一個(gè)變量(類似C語(yǔ)言的動(dòng)態(tài)變量)览濒。
- 值類型的存儲(chǔ)類型屬性可以是變量或者常量呆盖,計(jì)算型屬性跟計(jì)算屬性一樣只能定義成常量屬性。
- 注意4选应又!
- 必須給存儲(chǔ)型類型屬性,指定一個(gè)默認(rèn)值乏苦,因?yàn)轭愋捅旧碇昕福瑹o(wú)法在初始化過程中,使用構(gòu)造器給類型屬性賦值、
- 存儲(chǔ)型類型屬性是延遲初始化的席里,并且不要加lazy,多線程同時(shí)訪問也只會(huì)初始化一次叔磷。
5.1類型屬性語(yǔ)法
在Swift中,類型屬性是類型定義的一部分奖磁,寫在類型最外層花括號(hào)內(nèi)改基,作用域就是在該類型支持的范圍內(nèi)。
- 用關(guān)鍵字static來定義類型屬性
- 在類中咖为,用關(guān)鍵字class來支持子類對(duì)父類的實(shí)現(xiàn)進(jìn)行重寫秕狰。
// 只寫了只讀計(jì)算型類型屬性
struct MyStruct{
static var storedTypeProperty = "Some Value"
static var comutedTypeProperty : Int{
return 998
}
}
enum MyEnum{
static var storedTypeProperty = "Some Value"
static var comutedTypeProperty : Int{
return 998
}
}
class MyClass {
static var storedTypeProperty = "Some Value"
static var comutedTypeProperty : Int{
return 998
}
class var overridedableComutedTypeProperty : Int{
return 100
}
}
5.2獲取和設(shè)置類型屬性的值
跟實(shí)例的屬性一樣,類型屬性可以用點(diǎn)語(yǔ)法來訪問躁染,只是不需要通過實(shí)例鸣哀。