附錄A:KeyPath

目錄

KeyPath是一種特殊的資料型態,專門用來儲存「a.b.c.d」這樣的路徑。舉個例子,假設一個商店結構,裡面有商店名稱與創立年份,如下。

struct Store {
    var title: String
    var year: UInt
}
let store = Store(title: "老張服飾", year: 2003)

如果我們要取得商店的title與year時,我們可以使用常見的程式碼。

print(store.title)
print(store.year)

除此之外,我們也可以使用KeyPath,如下。

let titleKeyPath = \Store.title
let yearKeyPath = \Store.year
print(store[keyPath: titleKeyPath])
print(store[keyPath: yearKeyPath])

如果變數或常數宣告的時候需要明確地指定資料型態,而不是像上面這樣使用推論型態的話,語法如下。兩種型態寫法都可以,常數a只說明了他是KeyPath,但沒有實際指出KeyPath中存放的資料型態,而常數b詳細指出了型態,因此等號右邊的內容可以省略Store。

let a: KeyPath = \Store.title
let b: KeyPath<Store, String> = \.title

KeyPath的語法是「\.資料型態.屬性名稱」。現在我們來設計一個使用泛型的通用函數,只要傳入物件與KeyPath,就可以印出資料。

func doSomething<T, P>(_ object: T, keyPath: KeyPath<T, P>) {
    print(object[keyPath: keyPath])
}

呼叫方式如下:

doSomething(store, keyPath: \Store.title)
doSomething(store, keyPath: \Store.year)

此時其實KeyPath的資料型態已經可以從第一個參數得知,所以型態名稱就可以省略。

doSomething(store, keyPath: \.title)
doSomething(store, keyPath: \.year)

發表迴響