22.swift屬性


/*

存儲屬性

其實Swift中的存儲屬性就是以前學習OC中的普通屬性, 在結構體或者類中定義的屬性, 默認就是存儲屬性

*/


struct Person {

    var name: String

    var age: Int

}

var p:Person = Person(name: "lnj", age: 30)

p.name = "hm"

p.age = 50



/*

常量存儲屬性

常量存儲屬性只能在定義時或構造時修改, 構造好一個對象之後不能對常量存儲屬性進行修改

*/


struct Person2 {

    var name: String

    var age: Int

    let card: String // 身份證

}

var p2: Person2 = Person2(name: "lnj", age: 30, card: "123456")

p2.name = "hm"

p2.age = 50

// 構造好對象之後不能修改常量存儲屬性

//p2.card = "56789"



/*

結構體和類常量與存儲屬性的關係

結構體和枚舉是值類型

類是引用類型

*/


struct Person3 {

    var name: String

    var age: Int

}

let p3: Person3 = Person3(name: "lnj", age: 30)

// 因爲結構體是值類型, 所以不能修改結構體常量中的屬性

// 不能修改結構體/枚舉常量對象中的值, 因爲他指向的對象是一個常量

//p3.name = "hm"

// 不能修改結構體常量對象的值

//p3 = Person(name: "hm", age: 50)



class Person4 {

    var name: String = "lnj"

    var age: Int = 30

}

let p4:Person4 = Person4()

// 可以修改類常量中的值, 因爲他指向的對象不是一個常量

p4.name = "hm"

// 不可以修改類常量的指向

//p4 = Person4()



/*

延遲存儲屬性

Swift語言中所有的存儲屬性必須有初始值, 也就是當構造完一個對象後, 對象中所有的存儲屬性必須有初始值, 但是也有例外, 其中延遲存儲屬性可以將屬性的初始化推遲到該屬性第一次被調用的時候

懶加載應用場景:

    1.有可能不會用到

    2.依賴於其它值

*/


class Line {

    var start:Double = 0.0

    var end: Double = 0.0

    // 如果不是lazy屬性, 定義的時候對象還沒有初始化, 所以不能訪問self

    // 如果加上lazy, 代表使用時纔會加載, 也就是使用到length屬性時纔會調用self,

    // 而訪問一個類的屬性必須通過對象方法, 所以訪問時對象已經初始化完成了, 可以使用self

    lazy var length: Double = self.getLenght()

    // 通過閉包懶加載

    lazy var container: Array<AnyObject> = {

        print("懶加載")

//        return self.end - self.start

        var arrM = []

        return arrM as [AnyObject]

    }()

    func getLenght() ->Double

    {

        print("懶加載")

        return end - start

    }

}

var line = Line()

line.end = 150.0

//print(line.getLenght())

print("創建對象完畢")

print(line.length)

var arrM = line.container

arrM.append("1")

arrM.append(5)

print(arrM)



/*

計算屬性

1.Swift中的計算屬性不直接存儲值, 跟存儲屬性不同, 沒有任何的"後端存儲與之對應"

2.計算屬性用於計算, 可以實現settergetter這兩種計算方法

3.枚舉不可以有存儲屬性, 但是允許有計算屬性

setter 對象.屬性 =

getter var value = 對象.屬性

*/


struct Rect {

    var origion: (x: Double, y: Double) = (0, 0)

    var size: (w: Double, h: Double) = (0, 0)

    // 由於center的值是通過起點和寬高計算出來的, 所以沒有必要提供一個存儲屬性

//    var center: (x: Double, y: Double) = (0, 0)

    var center: (x: Double, y: Double) {

        get{

//            print("get")

           return (origion.x + size.w/2, origion.y + size.h/2)

        }

//        set(newCenter){

        set{

//            print("set \(newCenter)")

            // 注意: 計算屬性不具備存儲功能, 所以不能給計算屬性賦值, 如果賦值會發生運行時錯誤

            // 注意: setter可以自己傳遞一個參數, 也可以使用系統默認的參數newValue

            // 如果要使用系統自帶的參數, 必須刪除自定義參數

//            origion.x = newCenter.x - size.w / 2

//            origion.y = newCenter.y - size.h / 2

            origion.x = newValue.x - size.w / 2

            origion.y = newValue.y - size.h / 2

        }

    }

}

var r = Rect()

r.origion = (0, 0)

r.size = (100, 100)

//r.center = ((r.origion.x + r.size.w) / 2, (r.origion.y + r.size.h) / 2)

print("center.x = \(r.center.x) center.y = \(r.center.y)")

r.center = (100, 100)

print("origion.x = \(r.origion.x) origion.y = \(r.origion.y)")

print("center.x = \(r.center.x) center.y = \(r.center.y)")




/*

只讀計算屬性

對應OC中的readonly屬性, 所謂的只讀屬性就是隻提供了getter方法, 沒有提供setter方法

*/


class Line2 {

    var start:Double = 0.0

    var end: Double = 0.0

    // 只讀屬性, 只讀屬性必須是變量var, 不能是常量let

    // 例如想獲取長度, 只能通過計算獲得, 而不需要外界設置, 可以設置爲只讀計算屬性

    var length: Double{

        // 只讀屬性的簡寫, 可以省略get{}

//        get{

            return end - start

//        }

    }

}


var line2 = Line2()

line2.end = 100

print(line2.length)



/*

屬性觀察器,類似OC中的KVO, 可以用於監聽屬性什麼時候被修改, 只有屬性被修改纔會調用

有兩種屬性觀察器:

1.willSet, 在設置新值之前調用

2.didSet, 在設置新值之後調用

可以直接爲除計算屬性和lazy屬性之外的存儲屬性添加屬性觀察器, 但是可以在繼承類中爲父類的計算屬性提供屬性觀察器

因爲在計算屬性中也可以監聽到屬性的改變, 所以給計算屬性添加屬性觀察器沒有任何意義

*/

class Line3 {

    var start:Double = 0.0{

        willSet{

            print("willSet newValue = \(newValue)")

        }

        didSet{

            print("didSet oldValue = \(oldValue)")

        }

    }

    var end: Double = 0.0

}

var l = Line3()

l.start = 10.0



/*

類屬性

在結構體和枚舉中用static

在類中使用class, 並且類中不允許將存儲屬性設置爲類屬性

*/


struct Person5 {

    // 普通的屬性是每個對象一份

    var name: String = "lnj"

    // 類屬性是素有對象共用一份

    static var gender:String = "man"

    static var age:Int{

        return 30

    }

    func show()

    {

        print("gender = \(Person5.gender) name = \(name)")

    }

}

var p5 = Person5()

//print("gender = \(p.gender)")

print("gender = \(Person5.gender)")

var p6 = Person5()

// 類屬性是所有對象共用一份

print("gender = \(Person5.gender)")

p5.show()

// 可以將計算屬性設置爲類屬性

print("age = \(Person5.age)")




class Person6 {

    // 普通的屬性是每個對象一份

    var name: String = "lnj"

    // 類中不允許將存儲屬性定義爲類屬性

//    class var gender:String = "man"

    // 類中只能將計算屬性定義爲類屬性

    class var age:Int{

        return 30

    }

    func show()

    {

        print("age = \(Person6.age)")

    }

}

var p7 = Person6()

print("age = \(Person6.age)")

p7.show()


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章