iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
Software Development

給我 30 天,給你一輩子:Swift 從零開始系列 第 23

Day 23 | Swift Property 一家親:Type Property 和 Property Observer

  • 分享至 

  • xImage
  •  

Property 屬性

還記得上一篇介紹到 Stored Property 以及 Computed Property,也學習到如何使用 lazy 前綴字的使用,今天我們來介紹剩下兩種屬性取值的方式:

  • Type Property
  • Property Observer

Type Property

型別屬性,簡單來說就是只有 Type 本身能夠使用,不能透過實體來調用,然而要定義 Type Property 的話,必須在 Property 前方加上 static 前綴字:

struct Environment {
    static let testing = "testing-mock.com"
    static let staging = "staging-mock.com"
    let production = "production-real.com"
}

在使用時,我們就可以值就透過 Environment 本身來使用屬性,在 compiler time 時就已經決定好,把資料放在同一個記憶體,這麼做有一個好處就是可以共享同一個資源:

Environment.testing
Environment.staging

因為 production 並沒有加上 static 所以就不能直接用型別本身來調用,除非我們再建立一個實體,就可以使用 production,但是如果用實體就不能使用 static property。

let env = Environment()
env.production

不只 Struct 可以使用,在 Enum 以及 Class 中都是可以使用 Static Property

enum Sex {
    static var male = "男生"
    static var female = "女生"
}

class Math {
    static let pi = 3.14159
    static var eularsNumber: Double {
        2.718281828459045235
    }
}

還記得在前一篇提到的 Computed Property,這邊是只使用了 getter,這時候 eularsNumber 就變成 get-only property ,不能被指派值。

Class 前綴字

除了使用 static 使得 property 變成 type property 之外,你還可以使用 class

class 與 static 很相似,假使在類別中,差別在於 static 不允許子類別複寫父類別的屬性,class 可以:

class 車 {
    var 輪胎數量 = 4
    class var 顏色: String {
        "黑色"
    }
}

class 超級跑車: 車 {
    override class var 顏色: String {
        "銀色"
    }
}

但是假使我在子類別中,想要 override 父類別中不是 class property,就會發生錯誤:Cannot override with a stored property '輪胎數量'

https://ithelp.ithome.com.tw/upload/images/20200923/20118283Ej9T8Sb5Yx.png

小知識 1:Type Method

不只可以使用型別屬性,也可以使用型別方法:

定義在特定型別的方法,只屬於類別本身,不能被實體調用


Static Functions

class 食死人 {
    static func 阿瓦達索命咒() {
        print("Avada Kedavra!!!")
    }
}

可以使用 食死人.阿瓦達索命咒() 呼叫,但是如果是先實作 食死人 類別,再去呼叫,就會出現警告標語。

食死人.阿瓦達索命咒()      //Good
let 我是食死人 = 食死人()
我是食死人.阿瓦達索命咒()      //Static member '阿瓦達索命咒' cannot be used on instance of type '食死人'

而且 Static Functions 不能被覆寫。

class 貝拉・雷斯壯: 食死人 {
    override func 阿瓦達索命咒() {      //Method does not override any method from its superclass
        print("我是壞蛋,Avada Kedavra!!!")
    }
}

Class Functions

class 食死人 {
    class func 阿瓦達索命咒() {
        print("Avada Kedavra!!!")
    }
}

Class Functions 跟 Static Functions 很像,差在 Class Functions 允許子類別覆寫父類別的方法

這時候 貝拉・雷斯壯 就有客製的阿瓦達索命咒了。

class 貝拉・雷斯壯: 食死人 {
    override class func 阿瓦達索命咒() {
        print("我是壞蛋,Avada Kedavra!!!")
    }
}

但是方法一樣只屬於類別本身,不允許實體調用。

Property Observers

透過觀察屬性的變化來實作不同的事情,我們可以透過 Property Observers 來完成,有兩種觀察方式:

  • didSet:在屬性有變動之後
  • willSet:在儲存值之前

舉個範例:

class 倒數工具 {
    var 剩餘天數 = 100 {
        willSet(最新剩餘天數) {
            print("還剩下 \(最新剩餘天數) 天")
        }
        
        didSet(舊有天數) {
            if 舊有天數 >= 剩餘天數 {
                print("減少了 \(舊有天數 - 剩餘天數) 天")
            } else {
                print("超出原有天數")
            }
        }
    }
}

let tool = 倒數工具()
tool.剩餘天數 = 37

// 還剩下 37 天
// 減少了 63 天

也是可以省略帶入參數,如果不帶入參數

  • willSet 中,使用 newValue
  • didSet 中,使用 oldValue
class 倒數工具 {
    var 剩餘天數 = 100 {
        willSet {
            print("還剩下 \(newValue) 天")
        }
        
        didSet {
            if oldValue >= 剩餘天數 {
                print("減少了 \(oldValue - 剩餘天數) 天")
            } else {
                print("超出原有天數")
            }
        }
    }
}

let tool = 倒數工具()
tool.剩餘天數 = 37

// 還剩下 37 天
// 減少了 63 天

上一篇
Day 22 | Swift Property 一家親:Stored Property 和 Computed Property
下一篇
Day 24 | Swift Reference Type 與 Value Type
系列文
給我 30 天,給你一輩子:Swift 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言