一旦协议具有关联类型,就不能使用协议类型的 属性

Can't use property of a protocol type once protocol has associated type

我已经开始创建一个基础存储库 class,它将保存每个数据模型的数据,但我也希望它尽可能通用。 我还需要协议来通知这个存储库的消费者关于 in 的变化。想法是也有通用的数据更改机制,而不是根据数据类型定义 20 种协议。代码如下所示:

protocol BaseRepositoryDelegate {
    associatedtype dataType
    func didUpdateData(allData: [dataType], currentPage: [dataType], totalDataCount: Int, tag: Int?)
    func didGetError(error: ApiError)
}

class BaseRepository<T> {
    typealias dataType = T
    var delegate: BaseRepositoryDelegate?
    var tag: Int?

    private(set) public var data = [T]()
    private(set) public var currentPage = 0
    private(set) public var totalCount = 0

    init(delegate: BaseRepositoryDelegate, tag: Int? = nil) {
        self.delegate = delegate
        self.tag = tag
    }
}

我遇到的问题是 delegate 属性 导致错误 Protocol 'BaseRepositoryDelegate' can only be used as a generic constraint because it has Self or associated type requirements 并且我无法解决该问题并保留两个存储库的通用功能 class 和基本协议。关于如何处理这个问题有什么想法吗?

我的最终目标是有一个 class 即 SpecificRepository 可以继承 BaseRepository 并以某种方式提供一个可以为协议和 BaseRepository.

class SpecificRepository: BaseRepository<MySpecificType> {
    typealias dataType = MySpecificType

    // I can override methods here or properties based 
    // on my use-case, or I can add specific functionality.
}

如错误消息所建议的那样,改为将其设为通用类型。此外,typealias 声明毫无意义,因为您不使用它并且它与协议无关。通过向 class 声明添加 where 条件,将 T 与协议的关联类型连接(我还将 T 重命名为 DataType)

class BaseRepository<DataType, Delegate: BaseRepositoryDelegate> where Delegate.dataType == DataType{
    typealias dataType = DataType
    var delegate: Delegate?
    var tag: Int?

    private(set) public var data = [DataType]()
    private(set) public var currentPage = 0
    private(set) public var totalCount = 0

    init(delegate: Delegate, tag: Int? = nil) {
        self.delegate = delegate
        self.tag = tag
    }
}

简单示例

struct RepoDelegate: BaseRepositoryDelegate {
    typealias dataType = Int

    func didUpdateData(allData: [Int], currentPage: [Int], totalDataCount: Int, tag: Int?) {}
    func didGetError(error: ApiError) {}
}

let delegate = RepoDelegate()
let repo = BaseRepository(delegate: delegate, tag: nil)

要将此用于子class,您需要定义要扩展基础的数据类型和委托类型class

SpecificRepository: BaseRepository<MySpecificType, SpecificRepoDelegate>

我们匹配委托类型的地方

struct SpecificRepoDelegate: BaseRepositoryDelegate {
    typealias dataType = MySpecificType
    //...
}