介紹
Swift 4.2 中引入了一個新的文法
@dynamicMemberLookup
(動态成員查找)。使用
@dynamicMemberLookup
标記了目标(類、結構體、枚舉、協定),實作
subscript(dynamicMember member: String)
方法後我們就可以通路到對象不存在的屬性。
核心内容
-
:标記類、結構體、枚舉、協定@dynamicMemberLookup
-
:實作該方法,可以像數組和字典一樣,用下标的方式去通路屬性,通過所請求屬性的字元串名得到并傳回想要的值subscript(dynamicMember member: String)
基本使用
- 錯誤的代碼
struct Person {
}
let p = Person()
// 結構體沒有定義name屬性,是以會報錯
// Value of type 'Person' has no member 'name'
print(p.name)
複制
- 有了動态成員查找
// 标記
@dynamicMemberLookup
struct Person {
// 實作方法
subscript(dynamicMember member: String) -> String {
let properties = ["name":"Zhangsan", "age": "20", "sex": "男"]
return properties[member, default: "unknown property"]
}
}
let p = Person()
print(p.name) // 列印 Zhangsan
print(p.age) // 列印 20
print(p.sex) // 列印 男
複制
解讀
- 聲明了
後,即使屬性沒有定義,但是程式會在運作時動态的查找屬性的值,調用@dynamicMemberLookup
方法來擷取值。subscript(dynamicMember member: String)
-
方法的傳回值類型根據通路屬性的類型決定。subscript(dynamicMember member: String)
- 由于安全性的考慮,如果實作了這個特性,傳回值不能是可選值,一定要有值傳回。
多類型查找
既然是動态查找,如果兩個屬性類型不同,怎麼辦?解決辦法是重載
subscript(dynamicMember member: String)
方法。和泛型的邏輯類似,通過類型推斷來選擇對應的方法。
但是此時調用的時候,所有屬性必須顯示聲明類型,否則會報錯
。
@dynamicMemberLookup
struct Person {
subscript(dynamicMember member: String) -> String {
let properties = ["name":"Zhangsan", "sex": "男"]
return properties[member, default: "unknown property"]
}
subscript(dynamicMember member: String) -> Int {
let properties = ["age": 20]
return properties[member, default: 0]
}
}
let p = Person()
// 類型必須明确
let name: String = p.name
print(name) // 列印 Zhangsan
let age: Int = p.age
print(age) // 列印 20
let sex: String = p.sex
print(sex) // 列印 男
複制