一旦协议具有关联类型,就不能使用协议类型的 属性
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
//...
}
我已经开始创建一个基础存储库 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
//...
}