Мой уровень доступа к данным состоит из общего Repository
протокола
protocol Repository {
associatedtype T
func getAll() -> Promise<[T]>
}
и его конкретная реализация:
class FirebaseRepository<T: Model>: Repository {
func getAll() -> Promise<[T]> {
fatalError()
}
}
В основном, Repository
может быть RestRepository
, FirebaseRepository
, PlistRepositry
и т. Д. Хранилище данных используется бизнес-логикой:
/// My business logic
class ModelService<T: Repository> {
private let repository: T
public init(repository: T) {
self.repository = repository
}
}
Проблема возникает, когда я пытаюсь применить фабричный шаблон к хранилищу. Вот что я пришел первым:
/// Returns a concrete Repository implementation
class RepositoryFactory {
func makeRepository<T: Model>(type: T.Type) -> Repository {
return FirebaseRepository<T>()
}
}
и это определенно вызывает ошибку компилятора:
Protocol 'Repository' can only be used as a generic constraint because it has Self or associated type requirements
Единственный жизнеспособный вариант, к которому я пришел, это:
func makeRepository<T: Model>(type: T.Type, U: Repository) -> U {
return FirebaseRepository<T>() as! U
}
но, как вы понимаете, принудительное распаковывание не допускается в производственном коде.
Как заставить протоколы со связанными типами работать с шаблоном фабричного проектирования?