我正在尝试获取一个容器,该容器实现一组协议(protocol),我将这些协议(protocol)作为参数传递给原始容器上的函数。
struct Container {
let someProperty: String
let otherProperty: String
}
// Subcontainers
protocol Base {}
protocol SomePropertyContainer: Base {
var someProperty: String { get }
}
protocol OtherPropertyContainer: Base {
var otherProperty: String { get }
}
extension Container: SomePropertyContainer, OtherPropertyContainer {}
// Sub Container Provisioning Protocol
protocol SubContainerProviderProtocol {
func subContainer<T: Base>(protos: T.Type) -> T?
}
extension Container: SubContainerProviderProtocol {
func subContainer <T: Base>(protos: T.Type) -> T? {
return self as? T
}
}
// Example container
let subContainerProvider: SubContainerProviderProtocol = Container(someProperty: "Why does this not work!", otherProperty: "Seriously.")
启动并运行它可以让我将 ContainerProviderProtocol
注入(inject)消费者,同时让他们有可能自行指定他们真正想要的 SubContainer
。
例如只对 someProperty
感兴趣的类可能如下所示
// Example Container Provider consumer
class SomeClass {
let subContainerProvider: SubContainerProviderProtocol
init(subContainerProvider: SubContainerProviderProtocol) {
self.subContainerProvider = subContainerProvider
}
func printSomeProperty() {
let someProperty = subContainerProvider
.subContainer(protos: SomePropertyContainer.self)?
.someProperty
print(someProperty)
}
}
// Example call
let someClass = SomeClass(subContainerProvider: subContainerProvider)
someClass.printSomeProperty() // "Why does this not work!"
这个解决方案对于依赖注入(inject)和可测试性来说是不可思议的。
但是限制 T: Base
导致了编译器错误
In argument type 'SomePropertyContainer.Protocol', 'SomePropertyContainer' does not conform to expected type 'Base'
不指定符合 Base 将编译,但也允许将任何类型作为 T 传递。
我已经尝试在附加协议(protocol)等中使用关联类型,但还没有弄明白。虽然这个问题非常有趣,但我的想法已经用完了。
可能与(但不完全相同)https://bugs.swift.org/browse/SR-55 有关
最佳答案
这就是问题所在:在某些时候,您必须开始使用实际类型,而不仅仅是协议(protocol)。你的线路:
func container<T: Base>(protos: T.Type) -> T?
告诉编译器你要给这个函数一个类型,通常是 T
,它符合协议(protocol) Base
,而不是另一个协议(protocol)。你需要这样的东西:
class SPC: SomePropertyContainer {
var someProperty: String = ""
}
class SomeClass {
let containerProvider: ContainerProviderProtocol
init(containerProvider: ContainerProviderProtocol) {
self.containerProvider = containerProvider
}
func printSomeProperty() {
let someProperty = containerProvider
.container(protos: SPC.self)?
.someProperty
print(someProperty)
}
}
SPC 是一种符合 SomePropertyContainer 协议(protocol)的类型,它本身也符合 Base 协议(protocol),所以这就是您的代码所期望的。
关于Swift 泛型 - 协议(protocol)不符合协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51178395/