我的数据访问层由通用couchbase.BucketImpl.LookupInBuilder.prototype.executeAsync = () => {
return new Promise((resolve, reject) => {
this.execute((error, result) => {
if (error instanceof Error) {
reject(error);
} else {
resolve(result);
}
});
});
};
协议组成
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
但是,据您了解,强制可选的拆包在生产代码中是不可接受的。
如何使具有关联类型的协议与工厂设计模式一起使用?
答案 0 :(得分:1)
您可以使用类型擦除。这是一个示例:
protocol CustomProtocol {
associatedtype AssociatedType
func foo(argument: AssociatedType)
func bar() -> AssociatedType
}
如果您想直接使用CustomProtocol
,则会收到错误消息:
let array = [CustomProtocol]()
协议“ CustomProtocol”只能用作通用约束,因为它具有“自我”或相关类型要求
因此,您可以像Swift一样对它们的序列进行欺骗:
public struct AnyCustomProtocol<T>: CustomProtocol {
func bar() -> T {
fatalError("Needs implementation")
}
func foo(argument: T) {
}
}
let array = [AnyCustomProtocol<Any>]() // works fine
在这种情况下,您的问题解决方案将如下所示:
class Promise<T> {
}
protocol Model {
}
protocol Repository {
associatedtype T
func getAll() -> Promise<[T]>
}
class FirebaseRepository<T: Model>: AnyRepository<T> {
override func getAll() -> Promise<[T]> {
fatalError()
}
}
class AnyRepository<T>: Repository {
func getAll() -> Promise<[T]> {
fatalError()
}
}
class RepositoryFactory {
func makeRepository<T: Model>(type: T.Type) -> AnyRepository<T> {
return FirebaseRepository<T>()
}
}
__
要进一步阅读,您可以检查this和Official docs on Generics