繁体   English   中英

具有关联类型和工厂模式的协议?

[英]Protocols with associated type and factory pattern?

我的数据访问层由通用Repository协议组成

protocol Repository {
    associatedtype T
    func getAll() -> Promise<[T]>
}

及其具体实现:

class FirebaseRepository<T: Model>: Repository {
    func getAll() -> Promise<[T]> {
        fatalError()
    }
}

基本上, Repository可以是RestRepositoryFirebaseRepositoryPlistRepositry等。 Repository 被业务逻辑使用:

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

但如您所知,生产代码中不接受强制可选解包。

如何使具有关联类型的协议与工厂设计模式一起工作?

您可以使用类型擦除 下面是一个例子:

protocol CustomProtocol {
    associatedtype AssociatedType
    func foo(argument: AssociatedType)
    func bar() -> AssociatedType
}

如果你想直接使用CustomProtocol ,你会收到你的错误:

let array = [CustomProtocol]()

协议“CustomProtocol”只能用作通用约束,因为它具有 Self 或关联类型要求

所以你可以用同样的技巧,就像 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>()
        }
    }

__

如需进一步阅读,您可以查看泛型的官方文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM