符合通用协议方法返回 PAT

Conforming to generic protocol method returning PATs

我想声明类似于以下的通用协议:

protocol Factory {
    func createWidget<T, TWidget>(_ t: T) -> TWidget 
    where TWidget: Widget, TWidget.T == T
}

protocol Widget {
    associatedtype T
    func get() -> T
}

我希望我可以实现 Factory 的具体变体 return 使用隐藏的实现来实现他们自己的具体和不透明 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 的编译器给出错误 "Cannot convert return expression of type 'ConcreteWidget' to return type 'TWidget'"。

我也试过 ConcreteFactory return 一个 ConcreteWidget,但是错误是 ConcreteFactory 不符合 Factory.

这不行。当您 调用 您的 createWidget 方法时,您指定了两种类型 TTWidget.

struct MyWidget: Widget { 
   func get() -> Int { ... }
}

let widget: MyWidget = factory.createWidget(12)

在此示例中,TWidgetMyWidgetTInt。这很好地说明了为什么您的方法行不通。您不能将 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))
    }
}