关联类型的协议继承
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
的关联类型的具体类型是什么?”
在这种情况下,它要求您:
- 直接使用具体类型,即
let router: MyStartViewClass
与此 一致性声明 ,其他地方:class MyStartViewClass: StartRouterProtocol { ... }
)
- 或者,将对具体类型的需求向上推一层,作为通用约束,即
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
我有一个描述路由器行为的基本协议:
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
的关联类型的具体类型是什么?”
在这种情况下,它要求您:
- 直接使用具体类型,即
let router: MyStartViewClass
与此 一致性声明 ,其他地方:class MyStartViewClass: StartRouterProtocol { ... }
) - 或者,将对具体类型的需求向上推一层,作为通用约束,即
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