我有以下协议:
protocol PieceViewGateway {
subscript(_ identifier: PieceIdentifier) -> UIView {get}
}
我在很多地方都使用这种方式:
struct SomeKindOfThing {
let viewGateway: PieceViewGateway
}
这很好,很好。
以下是该协议具体实现的一个示例(还有其他实现):
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
}
}
我有几种类似的协议。另一个是PieceValueGateway
,它返回Int
而不是UIView
。
我不想为需要网关的各种不同“方面”实现类似ViewDictionaryPieceViewGateway
的功能。
我试图通过定义一个与网关关联的类型的协议来实现这一目标:
protocol PieceAspectGateway {
associatedtype Aspect
subscript(_ identifier: PieceIdentifier) -> Aspect {get}
}
然后我将PieceViewGateway
与此对应:
protocol PieceViewGateway: PieceAspectGateway {
subscript(_ identifier: PieceIdentifier) -> UIView {get}
}
但是,这会产生很多编译错误:
协议'PieceViewGateway'只能用作一般约束,因为它具有Self或相关类型要求
在我添加一致性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
用作协议,所有这些变体都会产生相同的错误。
有什么办法可以做到这一点?
谢谢。
答案 0 :(得分:1)
您可以将protocol
与associatedtype
和类型橡皮擦一起使用来创建任何种类的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>] = []
答案 1 :(得分:-1)
您要完成的工作非常简单:
protocol PieceAspectGateway {
associatedtype Aspect
subscript(_ identifier: PieceIdentifier) -> Aspect {get}
}
因此您具有此协议。当您想从中继承并使用更具体的类型时,可以使用通用约束:
protocol IntPieceAspectGateway: PieceAspectGateway where Aspect == Int {
...
}