是否有一种无需样板即可创建内部对象属性的访问器的方法?
这是带有样板的类的示例
public class Foo {
internal let bar: Bar
internal init(bar: Bar) {
self.bar = bar
}
private struct Bar: Codable {
let id: Int
let name: String
}
// MARK: - Boilerplate
public var id: Int {
return self.bar.id
}
public var name: String {
return self.bar.name
}
}
// Usage
do {
let bar: Bar = try data.decoded()
let foo = Foo(bar: bar)
print(foo.id)
print(foo.name)
} catch {
...
}
是否有一种无需编写样板的方法?对于具有更多属性的较大对象,这可能真的很有帮助
请注意:访问控制修饰符很重要
答案 0 :(得分:2)
Swift 5.1中的新增功能,您可以使用具有关键路径的动态成员查找。这对于这种“ has-a”情况非常有用,因为关键路径保持完整类型检查。这是一个简化的示例(不尝试反映您的实际情况):
struct Dog {
let name : String
}
@dynamicMemberLookup
struct Kennel {
let dog : Dog
subscript(dynamicMember kp:KeyPath<Dog,String>) -> String {
self.dog[keyPath:kp]
}
}
结果是,给定狗窝k
,我们可以获得k.name
作为获取k.dog.name
的一种方式。
但是说k.xxx
是非法的,因为Dog没有String xxx
属性;这就是我说要保留完整类型检查的意思。
旧方法是使用协议。这样,您可以使用协议扩展来注入样板。
protocol HasNameAndId {
var id: Int {get}
var name: String {get}
}
protocol WrapperOfHasNameAndId {
associatedtype T : HasNameAndId
var bar: T {get}
}
extension WrapperOfHasNameAndId { // boilerplate
var id: Int {
return self.bar.id
}
var name: String {
return self.bar.name
}
}
// ==============
struct Bar: HasNameAndId {
let id: Int
let name: String
}
class Foo : WrapperOfHasNameAndId {
let bar: Bar
init(bar: Bar) {
self.bar = bar
}
}
// =======
let f = Foo(bar: Bar(id: 1, name: "howdy"))
print(f.id) // 1
print(f.name) // "howdy"