我有以下设置:
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
的新实例之外,还有快速的解决方法吗?
答案 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> {}