【发布时间】:2021-04-12 13:04:48
【问题描述】:
我想在 BasePresenter 类中保留一个 Interactor 类,但在我的一生中,我无法弄清楚如何在 Swift 中轻松使用泛型。我想在基类中有一个函数(比如 BasePresenter interactorForType)。
public class InboxListPresenter: BasePresenter, ObservableObject {
public init(interactor: InboxListInteractor) {
super.init(router: InboxListRouter(viewData: viewData), interactor: interactor)
}
func findInboxNotifications() {
interactorForType(type: InboxListInteractor.self).findInboxNotifications() { inboxNotifications, errorCode in
// do something
}
}
}
这是我想要保存通用对象的 BasePresenter。我正在尝试使用协议 (ILibertyInteractor)
open class BasePresenter {
public let router:ILibertyRouter
public let interactor:ILibertyInteractor
public init(router:ILibertyRouter, interactor:ILibertyInteractor) {
self.router = router
self.interactor = interactor
}
func interactorForType<T>(type: T.Type) -> T {
return interactor as! T
}
func routerForType<T>(type: T.Type) -> T {
return router as! T
}
}
上面的 interactorForType 对我想要避免的交互进行了强制解包。另外,我也不想传入对象。我想使用协议和泛型来拥有一个返回类型 T 的泛型函数。
下面是我试图允许在上面的演示者中返回类型的开始。
public protocol ILibertyPresenter {
var router:ILibertyRouter { get }
}
public protocol ILibertyRouter {
}
public protocol ILibertyInteractor {
// associatedtype T
// func trueInteractor() -> T
}
【问题讨论】:
-
这能满足您的需求吗?
func interactorForType() -> ILibertyInteractor { return interactor } -
你不能改变 Swift 子类中方法的返回类型(甚至不能让它更专业)。您在这里尝试做的事情是不可能的。首先摆脱类继承(即 BasePresenter)。将类继承与泛型和协议混合使用会导致类型混乱。编写一些具体的演示者、路由器和交互器。查看实际代码重复发生的位置。从中提取协议或泛型(我经常发现在实践中你需要的很少)。强烈避免创建类型只是为了填补架构槽。确保它对你有用。
-
您的设计似乎自相矛盾。您对所有事情都使用协议,这意味着您不知道正在使用的具体类型,从而允许使用一种通用代码,因为当您调用协议上的方法时,它会动态地分派给适当的类。但另一方面,您希望使用真正的泛型,这取决于具体的类型信息,以便编译器可以静态调度方法。
-
你有一个 InboxListPresenter 和一个 InboxListInteractor 和一个 InboxListRouter 的事实强烈暗示这些类型没有发挥它们的作用并且没有提供任何灵活性。如果 InboxListInteractor 不能与 InboxListPresenter (或 "Mock"InboxListPresenter) 以外的任何东西一起使用,那么您实际上并不是在编写通用代码。您正在以复杂的方式编写非常具体的代码。具体代码很好(它太棒了!),但没有理由不能让它变得简单。
-
罗布是对的。不要将子类化与协议混合,您可以单独使用协议来完成所有操作。 InboxListPresenter 仍然需要是一个类,因为它需要是 ObserveableObject 才能与 SwiftUI 很好地配合。
标签: swift generics viper-architecture