天天看點

@dynamicMemberLookup

介紹

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) // 列印 男           

複制