我想声明类似于以下内容的通用协议:
protocol Factory {
func createWidget<T, TWidget>(_ t: T) -> TWidget
where TWidget: Widget, TWidget.T == T
}
protocol Widget {
associatedtype T
func get() -> T
}
我希望我可以实现Factory
的具体变体,并通过隐藏的实现返回它们自己的具体和不透明的Widget
。
这是无法构建的示例实现:
struct ConcreteFactory: Factory {
func createWidget<T, TWidget>(_ t: T) -> TWidget
where TWidget: Widget, TWidget.T == T {
// This line has an error…
return ConcreteWidget(widgetValue: t)
}
}
struct ConcreteWidget<T>: Widget {
let widgetValue: T
init(widgetValue: T) {
self.widgetValue = widgetValue
}
func get() -> T {
return widgetValue
}
}
但是,这不能编译。
在指示的行,Swift的编译器给出错误“无法将类型'ConcreteWidget'的返回表达式转换为类型'TWidget'”。
我也尝试过让ConcreteFactory
返回ConcreteWidget
,但是错误是ConcreteFactory
不符合Factory
。
答案 0 :(得分:3)
这行不通。当您调用您的createWidget
方法时,指定两种类型T
和TWidget
。
struct MyWidget: Widget {
func get() -> Int { ... }
}
let widget: MyWidget = factory.createWidget(12)
在此示例中,TWidget
是MyWidget
,而T
是Int
。这很好地说明了为什么您的方法行不通。您不能将ConcreteWidget<Int>
分配给类型MyWidget
的变量。
您需要的是用于小部件的类型擦除器。当前,您必须自己编写该代码,但是将来,编译器有望在需要时自动生成它们。
struct AnyWidget<T>: Widget {
private let _get: () -> T
init<Other: Widget>(_ other: Other) where Other.T == T {
_get = other.get
}
func get() -> T {
return _get()
}
}
这使您可以编写工厂协议和实现:
protocol Factory {
func createWidget<T>(_ t: T) -> AnyWidget<T>
}
struct ConcreteFactory: Factory {
func createWidget<T>(_ t: T) -> AnyWidget<T> {
return AnyWidget(ConcreteWidget(widgetValue: t))
}
}