【问题标题】:How can I get conditional protocol conformance with a protocol's parent?如何获得与协议父级的条件协议一致性?
【发布时间】:2019-09-05 13:57:48
【问题描述】:

我有以下设置:

protocol Resource : Codable {}

class A<T> {}

extension A where T : Codable {
    func doThingWithCodable() {}
}

let a = A<Resource>()

a.doThingWithCodable()
//Error: Protocol type 'Resource' cannot conform to Codable because
//only concrete types can conform to protocols.

我了解错误消息,并且阅读了许多关于泛型、协议和条件一致性的问答。我有许多符合Resource 协议的类,所以如果有办法让A&lt;Resource&gt; 知道它将始终使用符合Codable 的具体类型,那将非常方便,所以我仍然可以拥有A&lt;Resource&gt; 的一个实例,并且该实例可以访问其条件Codable 方法。我确实考虑过创建一个像A&lt;Codable&gt; 这样的实例,但我也需要Resource 协议中的一些属性。

除了为每个符合Resource 的具体类型创建一个A 的新实例之外,还有什么快速的方法可以解决这个问题吗?

【问题讨论】:

    标签: swift


    【解决方案1】:

    提出的问题是,“我怎样才能使有条件的协议符合协议的父级?”是没有意义的,因为一个协议总是符合它的父协议;没有“条件”。

    至于您的实际代码,问题在于短语A&lt;Resource&gt;。说 A&lt;Resource&gt; 不是 A 的 T 的正确解析。您需要将 T 解析为类、结构或枚举——而不是协议。

    比如你有一个符合Resource的B类,你可以声明

    let a = A<B>()
    

    一切都很好。

    如果有办法让A&lt;Resource&gt; 知道它将始终使用符合Codable 的具体类型

    好吧,正如我所说,只要 A 使用 确实 符合 Codable 的具体类型,您的代码就可以正常编译。因此,如果这就是 A 将一直使用的东西,那就没有什么可做的了。您当然可以告诉 A 它的 T 将始终符合 Resource(根据定义,它始终符合 Codable):

    class A<T:Resource> {}
    

    【讨论】:

    • 好的。所以简而言之,我最后一个问题的答案是否定的,对吗?按照您的描述进行设置需要为符合 Resource 的每个具体类型声明一个 A 实例。
    • 这就是泛型。每次使用时都必须解决它。具体来说。也许通用从来都不是你想要的?但你没有解释你想要什么。
    • 也许您只是希望 A 将 Resource 作为 参数 而根本不是泛型?
    • 我试图使用一个最小的可重现示例,如果我遗漏了一些细节,对不起。我正在使用NSCache 的子类。谢谢。
    • 是的,这可能是一个 xy 问题。我建议提出一个全新的问题。
    【解决方案2】:

    想一想:

    let a = A<Resource>()
    

    此语句试图创建类A 的实例并将其分配给a。编译器不知道这个资源到底是什么,它应该分配多少内存以及它应该运行什么优化;因为这里的Resource 可以是任何东西。

    要解决这个问题,您需要提供更多信息,即您已经知道的信息。

    struct CoffeeResouce: Resource {
        let isWarm: Bool
    }
    

    现在当你写这个时:

    let a: A<CoffeeResource> = A()
    

    编译器对类型及其内存要求非常了解。这是一种解决方法。

    或者通过声明类永久告诉类T符合协议。

    class A<T: Resource> {}
    

    【讨论】:

    • 是的,当我发布完我的答案后,我看到了你的答案。我只是保留它,因为它在描述中有所不同,并且可能会增加一点价值。你怎么看:我应该保留它还是删除它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2021-05-06
    • 2020-12-31
    相关资源
    最近更新 更多