簡體   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