Swift - реализация шаблона репозитория с помощью дженериков - PullRequest
0 голосов
/ 11 июня 2018

Я провел некоторое исследование шаблона хранилища, так как хочу использовать его в новом проекте, над которым я работаю.Однако у меня возникли проблемы при работе с генериками

Я следовал этому руководству здесь в качестве примера

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
    }
}

Это больше не работает.Теперь я получаю сообщение о том, что

Протокол 'Репозиторий' может использоваться только в качестве общего ограничения, потому что он имеет требования к Self или связанные с типами

Любые идеи о том, кто яздесь неправильно.Кажется, добавление relatedType приводит к тому, что это перестает работать.Мне бы очень хотелось, чтобы эта функциональность работала, поскольку я хочу иметь возможность внедрять шаблон локального или веб-хранилища в зависимости от текущего состояния приложения

Любая помощь будет очень полезной

1 Ответ

0 голосов
/ 11 июня 2018

Вам нужно сделать все остальное также общим:

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 вы не можете использовать протокол со связанными типами в качестве типа свойства / параметра и т. Д. Он должен сделать ваш кодболее безопасный тип.

...