Swift-05-存儲(chǔ)屬性與計(jì)算屬性

  • 屬性是將值跟特定的類、結(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)建后無法改變的區(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)建后無法被修改

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è)常量,那么無法修改該實(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用來管理和提供對這個(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")

簡單描述了一個(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的方法,屬性沒有對應(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)語法訪問,但是不能設(shè)置
  • 只讀計(jì)算屬性可以省略get和花括號
// 一個(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ì)算屬性和添加屬性觀察器。
  • 注意??!
  • 全局的常量或者變量都是延遲計(jì)算的,跟延遲存儲(chǔ)屬性不同的地方在于,全局的常量或者變量不需要標(biāo)記lazy。
  • 局部范圍的常量或者變量不會(huì)延遲計(jì)算。

5.類型屬性

實(shí)例的屬性屬于一個(gè)特定的實(shí)例,實(shí)例之間的屬性相互獨(dú)立,也可以為類型本身設(shè)置屬性,不管類有多少的實(shí)例,這些屬性只有唯一一份,這個(gè)就是類型屬性。

  • 類型屬性,比如所有實(shí)例都有一個(gè)常量(類似C語言的靜態(tài)常量),或者擁有一個(gè)變量(類似C語言的動(dòng)態(tài)變量)。
  • 值類型的存儲(chǔ)類型屬性可以是變量或者常量,計(jì)算型屬性跟計(jì)算屬性一樣只能定義成常量屬性。
  • 注意??!
  • 必須給存儲(chǔ)型類型屬性,指定一個(gè)默認(rèn)值,因?yàn)轭愋捅旧?,無法在初始化過程中,使用構(gòu)造器給類型屬性賦值、
  • 存儲(chǔ)型類型屬性是延遲初始化的,并且不要加lazy,多線程同時(shí)訪問也只會(huì)初始化一次。

5.1類型屬性語法

在Swift中,類型屬性是類型定義的一部分,寫在類型最外層花括號內(nèi),作用域就是在該類型支持的范圍內(nèi)。

  • 用關(guān)鍵字static來定義類型屬性
  • 在類中,用關(guān)鍵字class來支持子類對父類的實(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)語法來訪問,只是不需要通過實(shí)例。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容