Swift屬性


Swift 4語言為類,列舉或結構體提供關聯值的屬性。 屬性可以進一步分為儲存屬性和計算屬性。

儲存屬性和計算屬性的區別

儲存屬性 計算屬性
將常數和變數值儲存為範例 計算值而不是儲存值
由類和結構體提供 由類,列舉和結構提供

儲存和計算屬性都與範例型別相關聯。 當屬性與其型別值相關聯時,它將被定義為「型別屬性」。 儲存和計算屬性通常與特定型別的範例相關聯。 但是,屬性也可以與型別本身相關聯。 這些屬性稱為型別屬性。 還使用了屬性觀察者。

  • 觀察儲存屬性的值
  • 觀察從超類派生的繼承子類的屬性

儲存屬性

Swift 4引入了儲存屬性概念來儲存常數和變數的範例。 常數的儲存屬性由let關鍵字定義,變數的儲存屬性由var關鍵字定義。

  • 在定義期間,儲存屬性提供「預設值」
  • 在初始化期間,使用者可以初始化和修改初始值

參考以下程式碼 -

struct Number {
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

當使用playground執行上述程式時,得到以下結果 -

67
3.1415

考慮上面程式碼中的以下行 -

let pi = 3.1415

這裡,變數pi初始化為具有範例pi = 3.1415的儲存屬性值。 因此,每當參照範例時,它將僅儲存值:3.1415

儲存屬性的另一種方法是具有常數結構。 因此,結構體的整個範例將可視為「常數的儲存屬性」。

struct Number {
   var digits: Int
   let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

當使用playground執行上述程式時,得到以下結果 -

error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7

它不會將number重新初始化為8.7,而是返回一條錯誤訊息,指示number宣告為常數。

懶儲存屬性

Swift 4提供了一個名為「Lazy Stored Property」 的屬性,它不會在第一次初始化變數時計算初始值。 在變數宣告之前使用lazy修飾符將其作為惰儲存屬性。

使用懶屬性 -

  • 延遲物件建立。
  • 當屬性依賴於類的其他部分時,會延遲知道。

範例程式碼

class sample {
   lazy var no = number()    // `var` declaration is required.
}

class number {
   var name = "Swift 4"
}

var firstsample = sample()
print(firstsample.no.name)

當使用playground執行上述程式時,得到以下結果 -

Swift 4

範例變數

在Objective C中,儲存屬性還有用於備份目的的範例變數,用於儲存在儲存屬性中宣告的值。

Swift 4將這兩個概念整合到一個「儲存屬性」宣告中。 而不是具有相應的範例變數和備份值「儲存屬性」包含通過變數名稱,資料型別和記憶體管理功能在變數屬性的單個位置中定義的所有整合資訊。

計算屬性

不同於儲存值,計算屬性提供了getter和可選的setter來間接檢索和設定其他屬性和值。範例程式碼 -

class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0

   var middle: (Double, Double) {
      get {
         return (length / 2, breadth / 2)
      }

      set(axis){
         no1 = axis.0 - (length / 2)
         no2 = axis.1 - (breadth / 2)
      }
   }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

當使用playground執行上述程式時,得到以下結果 -

(150.0, 75.0)
-150.0
-65.0

當計算屬性將新值保留為undefined時,將為變數設定預設值。

計算屬性為唯讀屬性
計算屬性中的唯讀屬性被定義為具有getter,但沒有setter的屬性。 它始終用於返回值。 變數通過.運算子存取。但不能設定為其他值。

範例程式碼

class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}

var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

當使用playground執行上述程式時,得到以下結果 -

Swift 4 Properties
3.09

計算屬性作為屬性觀察者
在Swift 4中觀察和響應屬性值使用屬性觀察者(Property Observers)。 每次設定屬性值時,都會呼叫屬性觀察者。 除了延遲儲存的屬性,可以通過方法’覆蓋’將屬性觀察者新增到inherited屬性。

屬性觀察者可以由以下任何一個來定義 -

  • 在儲存值之前 - 將要設定
  • 儲存新值後 - 確定設定
  • 在初始化程式集中設定屬性時,無法呼叫didset觀察者。

參考範例程式碼

class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }

      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

當使用playground執行上述程式時,得到以下結果 -

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

本地和全域性變數

宣告區域性和全域性變數用於計算和觀察屬性。

區域性變數 全域性變數
在函式,方法或閉包上下文中定義的變數。 在函式,方法,閉包或型別上下文之外定義的變數。
用於儲存和檢索值。 用於儲存和檢索值。
儲存的屬性用於獲取和設定值。 儲存的屬性用於獲取和設定值。
計算屬性也可使用。 計算屬性也可使用。

型別屬性

屬性在型別定義部分中使用花括號{}定義,變數的範圍也先前已定義。 要定義值型別的型別屬性,使用static關鍵字,對於類型別,使用class關鍵字。

語法

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}

查詢和設定屬性

就像範例屬性一樣,查詢型別屬性並使用.運算子進行設定。 單獨使用型別語法而不是指向範例。範例程式碼如下所示 -

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0

   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

當使用playground執行上述程式時,得到以下結果 -

97
87