Swift - 使用泛型实现存储库模式
Swift - implementing repository pattern with generics
我一直在研究存储库模式,因为我想在我正在从事的新项目中使用它。但是我在使用泛型时遇到问题
我一直以本指南为例
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
}
}
这不再有效。我现在收到一条错误消息
Protocol 'Repository' can only be used as a generic constraint because
it has Self or associated type requirements
关于我在这里做错了什么的任何想法。似乎添加 associatedType 会导致它停止工作。我真的很想让这个功能正常工作,因为我希望能够根据应用程序的当前状态注入本地或基于 Web 的存储库模式
如有任何帮助,我们将不胜感激
您还需要使其他所有内容通用:
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 中,您不能使用具有关联类型的协议作为 property/parameter 等的类型。它应该使您的代码更加类型安全。
我一直在研究存储库模式,因为我想在我正在从事的新项目中使用它。但是我在使用泛型时遇到问题
我一直以本指南为例
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
}
}
这不再有效。我现在收到一条错误消息
Protocol 'Repository' can only be used as a generic constraint because it has Self or associated type requirements
关于我在这里做错了什么的任何想法。似乎添加 associatedType 会导致它停止工作。我真的很想让这个功能正常工作,因为我希望能够根据应用程序的当前状态注入本地或基于 Web 的存储库模式
如有任何帮助,我们将不胜感激
您还需要使其他所有内容通用:
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 中,您不能使用具有关联类型的协议作为 property/parameter 等的类型。它应该使您的代码更加类型安全。