1. 存儲屬性
Swift中的存儲屬性就是以前學習OC中的普通屬性 在結構體或者類中定義的屬性, 默認就是存儲屬性
struct Person { var name: String var age: Int } var p:Person = Person(name: "cdh", age: 20) p.name = "CDH" p.age = 50
2. 常量存儲屬性
常量存儲屬性隻能在定義時或構造時修改 構造好一個對象之後不能對常量存儲屬性進行修改
struct Person1 { var name: String var age: Int let card: String // 身份證 } var p1: Person1 = Person1(name: "cdh", age: 20, card: "123456") p1.name = "CDH" p1.age = 50 //構造好對象之後不能修改常量存儲屬性 //以下寫法是錯誤的 //p1.card = "56789"
3. 結構體和類常量與存儲屬性的關系
結構體和枚舉是值類型
因此不能修改結構體常量中的屬性 不能修改結構體/枚舉常量對象中的值, 因為他指向的對象是一個常量 類是引用類型
可以修改類常量中屬性的值, 因為他指向的對象不是一個常量
struct Person2 { var name: String var age: Int } let p2: Person2 = Person2(name: "cdh", age: 20) //因為結構體是值類型, 所以不能修改結構體常量中的屬性 //不能修改結構體/枚舉常量對象中的值, 因為他指向的對象是一個常量 //以下寫法錯誤 //p2.name = "CDH" //不能修改結構體常量對象的值 //以下寫法錯誤 //p2 = Person2(name: "CDH", age: 50)
class Person3 { var name: String = "cdh" var age: Int = 20 } let p3:Person3 = Person3() //可以修改類常量中屬性的值, 因為他指向的對象不是一個常量 p3.name = "CDH" //不可以修改類常量的指向 //以下寫法是錯誤的 //p3 = Person4()
4. 延遲存儲屬性
Swift語言中所有的存儲屬性必須有初始值, 也就是當構造完一個對象後, 對象中所有的存儲屬性必須有初始值 但是也有例外, 其中延遲存儲屬性可以將屬性的初始化推遲到該屬性第一次被調用的時候 懶加載應用場景:
有可能不會用到 依賴於其它值
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 = { print("懶加載") var arrM = [] return arrM as [AnyObject] }() func getLenght() ->Double { print("懶加載") return end - start } } var line = Line() line.end = 150.0 print("創建對象完畢") print(line.length) var arrM = line.container arrM.append("1") arrM.append(5) print(arrM) //輸出結果: //創建對象完畢 //懶加載 //150.0 //懶加載 //[1, 5]
5. 計算屬性
1.Swift中的計算屬性不直接存儲值
跟存儲屬性不同,沒有任何的”後端存儲與之對應” 2.計算屬性用於計算, 可以實現setter和getter這兩種計算方法 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) { get{ return (origion.x + size.w/2, origion.y + size.h/2) } set{ // 註意: 計算屬性不具備存儲功能, 所以不能給計算屬性賦值 // 如果賦值會發生運行時錯誤 // 註意: setter可以自己傳遞一個參數, 也可以使用系統默認的參數newValue // 如果要使用系統自帶的參數, 必須刪除自定義參數 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) print("center.x = \(r.center.x) center.y = \(r.center.y)") //輸出結果: center.x = 50.0 center.y = 50.0 r.center = (100, 100) print("origion.x = \(r.origion.x) origion.y = \(r.origion.y)") //輸出結果: origion.x = 50.0 origion.y = 50.0 print("center.x = \(r.center.x) center.y = \(r.center.y)") //輸出結果:center.x = 100.0 center.y = 100.0
6. 隻讀計算屬性
對應OC中的readonly屬性 所謂的隻讀屬性就是隻提供瞭getter方法, 沒有提供setter方法
class Line1 { var start:Double = 0.0 var end: Double = 0.0 // 隻讀屬性, 隻讀屬性必須是變量var, 不能是常量let // 例如想獲取長度 // 隻能通過計算獲得, 而不需要外界設置, 可以設置為隻讀計算屬性 var length: Double{ // 隻讀屬性的簡寫, 可以省略get{} return end - start } } var line1 = Line1() line1.end = 100 print(line1.length) //輸出結果: 100.0
7. 屬性觀察器
類似OC中的KVO 可以用於監聽屬性什麼時候被修改, 隻有屬性被修改才會調用 有兩種屬性觀察器:
1.willSet, 在設置新值之前調用 2.didSet, 在設置新值之後調用 可以直接為除計算屬性和lazy屬性之外的存儲屬性添加屬性觀察器 但是可以在繼承類中為父類的計算屬性提供屬性觀察器 因為在計算屬性中也可以監聽到屬性的改變 所以給計算屬性添加屬性觀察器沒有任何意義
class Line2 { var start:Double = 0.0{ willSet{ print("willSet newValue = \(newValue)") } didSet{ print("didSet oldValue = \(oldValue)") } } var end: Double = 0.0 } var l2 = Line2() l2.start = 10.0 //輸出結果: //willSet newValue = 10.0 //didSet oldValue = 0.0
8. 類屬性
在結構體和枚舉中用static 在類中使用class, 並且類中不允許將存儲屬性設置為類屬性
struct Person4 { // 普通的屬性是每個對象一份 var name: String = "cdh" // 類屬性是所有相同類對象共用一份 static var gender:String = "man" static var age:Int{ return 20 } func show() { print("gender = \(Person4.gender) name = \(name)") } } var p4 = Person4() print("gender = \(Person4.gender)") //輸出結果: gender = man var p5 = Person4() //類屬性是所有對象共用一份 print("gender = \(Person4.gender)") p5.show() //輸出結果: //gender = man //gender = man name = cdh //可以將計算屬性設置為類屬性 print("age = \(Person4.age)") //輸出結果:age = 20
class Person5 { // 普通的屬性是每個對象一份 var name: String = "cdh" // 類中不允許將存儲屬性定義為類屬性 // 下面為錯誤寫法 // class var gender:String = "man" // 類中隻能將計算屬性定義為類屬性 class var age:Int{ return 20 } func show() { print("age = \(Person5.age)") } } var p6 = Person5() print("age = \(Person5.age)") p6.show() //輸出結果: //age = 20 //age = 20