【问题标题】:Protocol inheritance with associated type具有关联类型的协议继承
【发布时间】:2021-09-21 17:45:48
【问题描述】:

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

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' 只能用作通用约束,因为它具有 Self 或关联类型要求

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

【问题讨论】:

    标签: swift protocols swift-protocols


    【解决方案1】:

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

    所以在这种情况下,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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多