我一直在对存储库模式进行一些研究,因为我想使用它正在开发的新项目。但是我遇到了使用泛型的问题
我一直在这里以此指南为例
https://medium.com/@frederikjacques/repository-design-pattern-in-swift-952061485aa
在解释它方面做得相当不错。然而,该指南留下了一个重要的细节..这是使用依赖注入与泛型。
在示例代码中,他显示了这个
class ArticleFeedViewModel {
let articleRepo:ArticleRepository
init( articleRepo:ArticleRepository = WebArticleRepository() ) {
self.articleRepo = articleRepo
}
}
如果您不使用泛型,那么它可以正常工作。但是一旦你将ArticleRepository更改为Repository示例......所以从
protocol ArticleRepository {
func getAll() -> [Article]
func get( identifier:Int ) -> Article?
func create( article:Article ) -> Bool
func update( article:Article ) -> Bool
func delete( article:Article ) -> Bool
}
到这个
protocol Repository {
associatedtype T
func getAll() -> [T]
func get( identifier:Int ) -> T?
func create( a:T ) -> Bool
func update( a:T ) -> Bool
func delete( a:T ) -> Bool
}
我再也无法让依赖注射工作了。所以,如果我尝试重新创建上面显示的模型。
class WebArticleRepository: Repository {
func getAll() -> [Article] {
return [Article()]
}
func get(identifier: Int) -> Article? {
return Article()
}
func create(a: Article) -> Bool {
return true
}
func update(a: Article) -> Bool {
return false
}
func delete(a: Article) -> Bool {
return true
}
}
class ArticleFeedViewModel {
let articleRepo:Repository
init( articleRepo:Repository = WebArticleRepository() ) {
self.articleRepo = articleRepo
}
}
这不再适用。我现在收到错误说
协议'存储库'只能用作通用约束因为 它有自我或相关的类型要求
关于我在这里做错了什么的任何想法。似乎添加associatedType会导致此操作停止。我真的想让这个功能正常工作,因为我希望能够根据应用程序的当前状态注入本地或基于Web的存储库模式
任何帮助都会得到很多帮助
答案 0 :(得分:2)
您还需要将其他所有内容都设为通用:
protocol Repository {
associatedtype RepositoryType
func getAll() -> [RepositoryType]
func get( identifier:Int ) -> RepositoryType?
func create( a:RepositoryType ) -> Bool
func update( a:RepositoryType ) -> Bool
func delete( a:RepositoryType ) -> Bool
}
class WebArticle { }
class WebArticleRepository: Repository {
typealias RepositoryType = WebArticle
func getAll() -> [WebArticle] {
return [WebArticle()]
}
func get(identifier: Int) -> WebArticle? {
return WebArticle()
}
func create(a: WebArticle) -> Bool {
return true
}
func update(a: WebArticle) -> Bool {
return false
}
func delete(a: WebArticle) -> Bool {
return true
}
}
class ArticleFeedViewModel<T : Repository> {
let articleRepo: T
init( articleRepo: T) {
self.articleRepo = articleRepo
}
}
// you cannot have the optional parameter in the init, instead, you can extract the following line to a method
ArticleFeedViewModel(articleRepo: WebArticleRepository())
在Swift中,你不能使用具有相关类型的协议作为属性/参数的类型等。它应该使你的代码更加类型安全。