swift - 通过指定类型将 "protocol with associated type"转换为常规协议(protocol)

标签 swift swift-protocols

我有以下协议(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)时,所有这些变体都会产生相同的错误。

有什么办法可以实现吗?

谢谢。

最佳答案

您可以使用带有associatedtypeprotocol 和类型橡皮擦来创建任何类型的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/

相关文章:

swift - 为什么我必须执行 append<S : Sequence>(contentsOf newElements: S) in my custom RangeReplaceableCollection

SwiftUI:内容是图像的 ViewModifier

ios - ADInterstitialAd 不适用于 ipad swift

swift - 如何用可选方法包装协议(protocol)?

RawRepresentable 上的 Swift 扩展没有可访问的初始化器

swift - 传递给函数的 CoreData 类型

swift - 扩展协议(protocol)以实现不同的行为

php - gcm推送通知: first success,然后未在IOS中注册

swift - swift 的BSON?

ios - Array 的 Property Observer,获取更改后的索引