天天看點

Swift4.0 — 屬性

一、類的定義

Swift與Objective-C定義類的差別

Objective-C:一般需要2個檔案,1個.h聲明檔案和1個.m實作檔案

Swift:隻需要1個.swift檔案

Swift中類的定義格式

class 類名  {
     // ... 屬性和方法
 }
           

二、屬性

1.什麼是屬性

  Swift中的屬性(Properties),就類似于其他面向對象語言中的成員變量

2.屬性的分類

按照官方文檔的說明,屬性可以分為以下幾種

(1)存儲屬性(Stored Properties)

(2)計算屬性(Computed Properties)

(3)類型屬性(Type Properties)

3.存儲屬性

1)簡單說明

存儲屬性:存儲屬性就是存儲在對象(執行個體)中的一個變量或者常量

存儲屬性類似于其他面向對象語言中的成員變量

class Person {
     var age: Int = 
     var height: Double = 
     let life = 
 }
           

說明:

Person類中定義了3個存儲屬性

2個變量存儲屬性:Int類型的age、Double類型的height

1個常量存儲屬性:Int類型的life

系統并不會自動初始化上面的3個存儲屬性,需要進行手動初始化

2)存儲屬性的讀寫

  如何讀寫存儲屬性?

  直接通過點運算符(.),就可以讀寫某個對象的存儲屬性  

class Person {
     var age: Int = 
     let life = 
 }
 let p = Person()
 p.age = 
 print("p的生命是\(p.life), p的年齡是\(p.age)")
           

說明:

第5行:建立Person對象

第6行:給對象p的age屬性指派

第7行:通路對象p的life屬性值和age屬性值

3)延遲存儲屬性

什麼是延遲存儲屬性?

延遲存儲屬性是第一次使用時才進行初始化的屬性

使用@lazy來辨別一個延遲存儲屬性

class Person {
     @lazy var dog: String = String()
 }
 let p = Person()
 println(p.dog)
           

說明:

  執行第5行代碼時,才會去初始化dog屬性,才真正建立了String對象

延遲存儲屬性的使用注意:延遲存儲屬性必須是變量,不能是常量

延遲存儲屬性的好處:讓某些資源用到時再去加載,避免一些不必要的資源浪費

4.計算屬性

(1)什麼是計算屬性

跟存儲屬性不一樣的是,計算屬性不是直接存儲值,而是提供get和set

get:用來取值,封裝取值的過程

set:用來設值,封裝設值的過程

(2)代碼示例:

class Square {
      // 正方形的寬度
        var width: Double = 
      // 正方形的周長
        var girth: Double {
          get {
              // 周長 = 寬度 * 4
                  return width * 
          }
         set(newGirth) {
             // 寬度 = 周長 / 4
                    width = newGirth / 
         }
     }
 }
           

計算屬性舉例:

let s = Square()
 s.width = 
 print(s.girth)
 s.girth =  
 print(s.width) 
           

說明:

第3行代碼:調用girth屬性的get,輸出結果是40

第4行代碼:調用girth屬性的set,并且把200傳遞給newGirth參數

第5行代碼:輸出結果是50

(3)簡便的set

  set也可以不特意指定新值的參數名,新值的預設參數名叫做newValue

var girth: Double {
     get {
         return width * 
     }
     set {
         width = newValue / 
     }
 }
 s.girth =  
           

說明:

  執行第9行代碼時:第6行中newValue的值就是200

  

(4)計算屬性的使用注意

  1)因為計算屬性的值不是固定的,是以隻能用var修飾計算屬性,不能用let

class Square {
      var girth: Double {
          get {
              return girth
          }
          set(newGirth) {
              girth = newGirth
          }
      }
 }
           

說明:上面的代碼會引發死循環,第4行代碼會引發循環調用get,第7行代碼會引發循環調用set。

2)一個屬性不能既是存儲屬性,又是計算屬性

class Square {
      var girth: Double =  {
          get {
              return 
          }
          set() {
              
          }
      }
 }
           

說明:上面的代碼是錯誤的

(5)隻讀計算屬性

什麼是隻讀計算屬性?隻提供get,沒有set的計算屬性

class Square {
      var width: Double = 
      var girth: Double {
          get {
              return width * 
          }
      }
  }
  let s = Square()
 s.girth = 
           

說明:第10行代碼會報錯

  隻讀計算屬性的簡寫。隻讀計算屬性可以省略get關鍵字

class Square {
     var width: Double = 
     var girth: Double {
         return width * 
     }
 }
 let s = Square()
 s.girth =  
           

說明:第8行代碼會報錯

5.類型屬性

(1)什麼是類型屬性?

用class關鍵字修飾的屬性,就是類型屬性,也可以稱為“類屬性”

class修飾的類型屬性隻能是計算屬性,不能是存儲屬性

代碼示例:

class Circle {
     class var PI : Double  {
         return 
     }
 }
           

說明:第2行定義的屬性PI,就是一個類型屬性

(2)類型屬性的特點

  一個類隻會有一份,類的多個執行個體對象都共享這唯一的一份

  類型屬性的使用:類型屬性不依賴于對象而存在,是以用類名來通路

  println(Circle.PI)

三、屬性螢幕

1.什麼是屬性螢幕?

有時,需要在屬性值被修改的時候做出響應,這種情況下就可以用屬性螢幕

屬性螢幕,可以監視屬性值的修改過程

計算屬性可以直接在set中監聽屬性值的改變,而存儲屬性沒有set

可以為存儲屬性添加willSet和didSet兩個屬性螢幕

(1)willSet:

在設定新的屬性值之前調用

會将新的屬性值作為參數傳入,參數名預設是newValue

(2)didSet:

在設定新的屬性值之後調用

會将舊的屬性值作為參數傳入,參數明預設是oldValue

2.代碼示例

class Square {
      var width: Double =  {
          willSet {
              print("willSet---\(newValue)")
          }
          didSet {
              print("didSet---\(oldValue)")
          }
      }
 }
 let s = Square()
 s.width = 
           

列印結果:

willSet—10.0

didSet—0.0

3.使用注意

class Square {
     var width: Double =  {
         willSet { }
         didSet { width =  }
     }
 }
 let s = Square()
 s.width = 
 print(s.width)
           

代碼說明:

willSet和didSet在屬性初始化過程中不會被調用,隻會當屬性的值在初始化之外的地方被設定時被調用
第2行代碼的初始化不會引發willSet和didSet的調用
第8行代碼的指派會引發willSet和didSet的調用
如果在didSet螢幕裡為屬性指派,這個值會替換之前設定的值
第4行對width屬性進行了再次指派,覆寫了第8行賦的值,是以第9行的輸出結果是20
           
willSet、didSet和set、get不能共存