关联类型的协议继承

Protocol inheritance with associated type

我有一个描述路由器行为的基本协议:

protocol BaseRouterProtocol: AnyObject {
    associatedtype View: MainView
    func dismiss(viewController: ViewController<View>?)
}

extension BaseRouterProtocol {
    func dismiss(viewController: ViewController<View>?) {
        viewController?.navigationController?.popViewController(animated: true)
    }
}

我想将此协议应用于另一个这样的协议:

protocol StartRouterProtocol: BaseRouterProtocol where View == StartView {
    func showTermsVC()
    func showSignInVC()
}

但是当我创建这种类型的变量时:

let router: StartRouterProtocol

编译器报错:

Protocol 'StartRouterProtocol' can only be used as a generic constraint because it has Self or associated type requirements

如果我描述了我期望的类型,为什么会发生这种情况?

一旦协议具有关联类型,该协议就不能单独用作实例声明的类型——只能用于通用约束和声明一致性。

所以在这种情况下,Swift 是说“是的,但是 StartRouterProtocol 的关联类型的具体类型是什么?”

在这种情况下,它要求您:

  1. 直接使用具体类型,即 let router: MyStartViewClass 与此 一致性声明 ,其他地方:class MyStartViewClass: StartRouterProtocol { ... })
  2. 或者,将对具体类型的需求向上推一层,作为通用约束,即
class MyRouterController<T: StartRouterProtocol> {
    let router: T
}

这可能不是您所希望的,但遗憾的是关联类型增加了您使用协议的方式的复杂性,尤其是当您熟悉其他语言的泛型和接口时。 (即 Java/C# 个接口)

您可以使用称为“类型擦除”的概念解决关联类型的某些方面问题——但这可能会导致其他问题和复杂性。

这里有一些可能有帮助的进一步阅读:https://medium.com/monstar-lab-bangladesh-engineering/swift-from-protocol-to-associatedtype-then-type-erasure-a4093f6a2d08