类或是struct声明为 @dynamicMemberLookup 后,并实现 subscript(dynamicMember:), 就可以用带 点的语法来访问对应的数据了。
@dynamicMemberLookup
class TestData<Value> {
var value : Value
var name : String
init(_ v : Value, name : String) {
self.value = v
self.name = name
}
//subscript(dynamicMember:) 只能用 String 或 KeyPath 作为参数
subscript(dynamicMember pro : String) -> Bool {
return true
}
subscript<T>(dynamicMember key : KeyPath<Value, T>) -> T {
value[keyPath: key]
}
}
//使用带点语法访问数据时有优先级
let data = TestData("b", name: "haha”) //Value 泛型推导为 “b”的类型,也就是String
//优先级1: 访问已有的属性,比如 TestData 的name属性。
let name = data.name
//优先级2: 访问 keypath对应的 Value类型所拥有的属性。 这里Value是String,那么count 访问的就是 value.count
let count = data.count //值为1
//优先级3: 访问 String类型参数的subscript
let value = data.haha //返回 true
dynamicMemberLookup 是否安全? 是安全的。 如果用String 来访问,那么在实现的 subscript 里确保了返回数据是安全的。 如果用keyPath 访问,不存在的keyPath 无法通过编译。
可以声明多个 相同参数类型,但不同返回值的subscript。编译时通过返回值来区分调用哪个subscript let b : Bool = data.haha let c : String = data.haha
不能给已有类和结构添加 dynamicMemberLookup 功能