我正在尝试编写一个协议,允许我在我的应用程序中版本模型。为了做到这一点,我编写了以下VersionManager

class VersionManager<Type: Decodable> {
    private var database: Database

    init(database: Database) {
        self.database = database
    }

    var versions: [Type] {
        return []
    }
}

之后,我编写了一个可以添加到模型中的协议:
protocol Versionable {

}

extension Versionable {
    private var manager: VersionManager<Restaurant> {
        return VersionManager<Restaurant>(database: Database.shared)
    }

    public var versions: [Restaurant] {
        return manager.versions
    }
}

现在,我面临的问题是,我试图动态地传递类型,而不是硬编码,就像我现在对于Restaurant所做的那样。
所以我试着把协议改成:
protocol Versionable {
    var kind: Decodable.Type { get }
}

然后我想把kind传递到VersionManager。但是,当我尝试Xcode抛出这个错误时:Expected '>' to complete generic argument list
还有别的办法吗?

最佳答案

如果要在protocol中使用泛型,则需要使用associatedtype

protocol Versionable {
    associatedtype Model: Decodable
}

extension Versionable {
    private var manager: VersionManager<Model> {
        return VersionManager<Model>(database: Database.shared)
    }

    public var versions: [Model] {
        return manager.versions
    }
}

要实现Versionable协议的模型必须解决以下类型:
struct SomeModel: Versionable {
    typealias Model = Int
}

SomeModel().versions // [Int]

我猜您的示例中的Restaurant指的是实现Versionable的模型。在这种情况下,您只需在协议扩展内使用Self引用即可:
protocol Versionable: Decodable {
}

extension Versionable {
    private var manager: VersionManager<Self> {
        return VersionManager<Self>(database: Database.shared)
    }

    public var versions: [Self] {
        return manager.versions
    }
}

struct SomeModel: Versionable {}
SomeModel().versions // [SomeModel]

请注意,Versionable协议现在需要Decodable一致性,因为VersionManager<Type: Decodable>通用约束。

10-08 00:05