Swift 如何访问内部对象';不带样板的超类的s属性

Swift 如何访问内部对象';不带样板的超类的s属性,swift,encapsulation,abstraction,Swift,Encapsulation,Abstraction,有没有一种方法可以在没有样板的情况下创建内部对象属性的访问器 下面是一个带有样板的类的示例 public class Foo { internal let bar: Bar internal init(bar: Bar) { self.bar = bar } private struct Bar: Codable { let id: Int let name: String } // MAR

有没有一种方法可以在没有样板的情况下创建内部对象属性的访问器

下面是一个带有样板的类的示例

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 {
    ...
}
有没有一种不用写样板的方法?对于具有更多属性的较大对象,这可能非常有用


请注意:访问控制修饰符非常重要,在Swift 5.1中新增了

,您可以使用带有密钥路径的动态成员查找。这对于这种“has-a”情况非常有效,因为关键路径保持完整的类型检查。下面是一个简化的示例(没有试图反映您的实际情况):


Swift 5.1中的新增功能是,您可以使用带有密钥路径的动态成员查找。这对于这种“has-a”情况非常有效,因为关键路径保持完整的类型检查。下面是一个简化的示例(没有试图反映您的实际情况):



你怎么能让bar:bar=try data.decoded()out
Foo
Bar
Foo
中不是私有的吗?Hello@RickyMo这是在同一个代码库中,在项目之外这是不可能的。这个问题是为了封装和单一责任而提出的。在Swift 5.1中,你可以进行“动态成员查找”,比较一下,让我试试那个。@MartinR是的,我也独立地意识到了这一点,并在我的答案中添加了一个关于它的注释。很好。你怎么能
Let bar:bar=try data.decoded()
outside
Foo
?在
Foo
中不是
Bar
私有的吗?Hello@RickyMo这是在同一个代码库中,在项目之外这是不可能的。这个问题是出于封装目的和单一责任而提出的。在Swift 5.1中,您可以进行“动态成员查找,“比较一下,让我试试这个。@MartinR是的,我也独立地意识到了这一点,并在我的答案中添加了一条关于它的注释。观点很好。我想这是最好的解决方案,我必须编写代码,但至少样板文件在其他地方。但它仍然不起作用,因为我需要
扩展包装器的名字和ID
公开,而我没有他
协议包装器的名字和ID
需要是内部范围。我想这是无法回避的不?好吧,在Swift 5.1中,有一种全新的方法可以做到这一点。噢,我看到Martin R在评论中指出了这一点。在我的回答中添加了一些关于这一点的内容。我认为这是你想要直接进入的。有一个如果我没记错的话,这是WWDC2019会话中的一个很好的例子。它是关于实现COW值类型,并将属性转发到内部引用类型。@MartinR是的,这是会话415。但是,此功能作为自动转发到包装对象的一种方式很有价值。不幸的是,没有类似的自动方法呼叫转移,虽然我不明白为什么他们最终不能添加它。我明白了,不幸的是,我要求的这个功能仍然不可用。我想这是最好的解决方案,我必须编写代码,但至少样板文件在其他地方。但它仍然不起作用,因为我需要扩展包装器ndId要公开,我认为域名和ID的协议包装器必须是内部的。我想这是无法回避的,不?好吧,在Swift 5.1中有一种全新的方法可以做到这一点。噢,我看到Martin R在评论中指出了这一点。在我的回答中添加了一些关于这一点的内容。我认为这是directly你想加入。如果我没记错的话,在其中一次WWDC2019会话会谈中有一个很好的例子。它是关于实现COW值类型,并将属性转发到内部引用类型。@MartinR是的,这是会话415。但是,作为一种通常自动转发到包装对象的方式,此功能很有价值。Unfo虽然我不明白为什么他们最终不能添加自动方法呼叫转移,但实际上没有类似的功能。我明白了,不幸的是,我要求的这个功能仍然不可用。
struct Dog {
    let name : String
}
@dynamicMemberLookup
struct Kennel {
    let dog : Dog
    subscript(dynamicMember kp:KeyPath<Dog,String>) -> String {
        self.dog[keyPath:kp]
    }
}
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"