我有以下协议(protocol):
protocol PieceViewGateway {
subscript(_ identifier: PieceIdentifier) -> UIView {get}
}
我在很多地方都以这样的方式使用它:
struct SomeKindOfThing {
let viewGateway: PieceViewGateway
}
一切都很好,非常好。
这是协议(protocol)具体实现的一个示例(还有其他实现):
struct ViewDictionaryPieceViewGateway: PieceViewGateway {
let viewDictionary: [PieceIdentifier: UIView]
subscript(identifier: PieceIdentifier) -> UIView {
guard let item = viewDictionary[identifier] else {
fatalError("Gateway has no value for key: \(identifier)")
}
return item
}
}
我有几个这样的协议(protocol)。另一个是 PieceValueGateway
,它返回 Int
而不是 UIView
。
我不想为需要网关的各种不同“方面”实现类似 ViewDictionaryPieceViewGateway
的东西。
我试图通过定义一个具有关联类型的协议(protocol)来模拟网关来实现这一点:
protocol PieceAspectGateway {
associatedtype Aspect
subscript(_ identifier: PieceIdentifier) -> Aspect {get}
}
然后我会让 PieceViewGateway
符合这个:
protocol PieceViewGateway: PieceAspectGateway {
subscript(_ identifier: PieceIdentifier) -> UIView {get}
}
但是,这会产生很多编译错误:
Protocol 'PieceViewGateway' can only be used as a generic constraint because it has Self or associated type requirements
在我添加一致性 PieceViewGateway: PieceAspectGateway
之前,错误在代码上报告很好。例如,SomeKindOfThing
声明它有一个 let viewGateway: PieceViewGateway
。
我也试过这样符合:
protocol PieceViewGateway: PieceAspectGateway where Aspect == UIView {
subscript(_ identifier: PuzzlePieceIdentifier) -> UIView {get}
}
像这样:
protocol PieceViewGateway: PieceAspectGateway {
typealias Aspect = UIView
subscript(_ identifier: PuzzlePieceIdentifier) -> UIView {get}
}
...但是当 PieceViewGateway
用作协议(protocol)时,所有这些变体都会产生相同的错误。
有什么办法可以实现吗?
谢谢。
最佳答案
您可以使用带有associatedtype
的protocol
和类型橡皮擦来创建任何类型的Gateway
。请看下面,
protocol PieceAspectGateway {
associatedtype Aspect
subscript(_ identifier: PieceIdentifier) -> Aspect {get}
}
struct AnyGateway<T>: PieceAspectGateway {
let dictionary: [PieceIdentifier: T]
subscript(identifier: PieceIdentifier) -> T {
guard let item = dictionary[identifier] else {
fatalError("Gateway has no value for key: \(identifier)")
}
return item
}
}
用法
let viewGateway: AnyGateway<UIView>
let viewGateways: [AnyGateway<UIView>] = []
let intGateway: AnyGateway<Int>
let intGateways: [AnyGateway<Int>] = []
let stringGateway: AnyGateway<String>
let stringGateways: [AnyGateway<String>] = []
关于swift - 通过指定类型将 "protocol with associated type"转换为常规协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53850726/