如何获得与协议父级的条件协议一致性?

时间:2019-09-05 01:57:01

标签: swift

我有以下设置:

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<Resource>知道它将始终与符合{ {1}},因此我仍然可以拥有一个Codable实例,并且该实例可以访问其条件A<Resource>方法。我确实考虑过只制作一个像Codable这样的实例,但是我也需要A<Codable>协议内部的一些属性。

除了为符合Resource的每种具体类型创建A的新实例之外,还有快速的解决方法吗?

2 个答案:

答案 0 :(得分:2)

提出的问题是:“我如何获得与协议父级的条件协议一致性?”是没有意义的,因为协议始终与其父协议一致;没有“条件”。

对于您的实际代码,问题在于短语A<Resource>。说A<Resource>不是A的T的正确解析。您需要将T解析为类,结构或枚举,而不是作为协议。

例如,如果您有一个符合Resource的B类,则可以声明

let a = A<B>()

一切都很好。

  

如果有一种方法可以让A<Resource>知道它将始终与符合Codable的具体类型一起使用

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

class A<T:Resource> {}

答案 1 :(得分:0)

只需考虑一下:

let a = A<Resource>()

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

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

struct CoffeeResouce: Resource {
    let isWarm: Bool
}

现在,当您编写此代码时:

let a: A<CoffeeResource> = A()

编译器非常了解类型及其内存要求。这是解决问题的一种方式。

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

class A<T: Resource> {}