Ash*_*lls 4 generics swift swift-protocols
根据我上一个问题的答案,我有 2 个协议\xe2\x80\xa6
\n\nprotocol Filters: Encodable { \n}\n\nprotocol QueryParameters: Encodable {\n associatedtype T: Filters\n var page: Int { get }\n var filters: T { get }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后对于类型Transaction,我有\xe2\x80\xa6
struct TransactionFilters: Filters {\n var isWithdrawal: Bool\n}\n\nstruct TransactionParamters<T: Filters>: QueryParameters {\n var page: Int\n var filters: T\n}\nRun Code Online (Sandbox Code Playgroud)\n\n到目前为止一切都很好。
\n\n接下来我添加一个协议 ,Filterable并且我希望任何符合该协议的类型都Filterable能够返回参数,如下所示\xe2\x80\xa6
protocol Filterable {\n func parameters() -> QueryParameters\n}\n\nstruct Transactions: Filterable {\n func parameters() -> QueryParameters {\n let transactionFilters = TransactionFilters(isWithdrawal: true)\n return TransactionParamters(page: 1, filters: transactionFilters)\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n但我最终得到\xe2\x80\xa6
\n\n\n\n\n错误:协议“QueryParameters”只能用作通用约束,因为它具有 Self 或关联的类型要求
\n
这似乎是一个非常简单的要求,但我花了两天时间尝试了我能想到的所有组合以使其发挥作用。现在我终于认输了。
\n\n我需要做什么来解决这个问题?
\n正如我在评论中提到的。您的代码中缺少的是associatedtype永远不会真正成为一种类型。在您的代码中的任何地方都没有structs将类型分配给associatedtype. 如果您想要通用filterable功能,您可以按照以下方式做一些事情:
// Your generic Filters with required properties
protocol Filters: Encodable {
var isWithdrawal: Bool { get }
init(isWithdrawal: Bool)
}
// Your generic query parameters
protocol QueryParameters: Encodable {
associatedtype F: Filters
var page: Int { get }
var filters: F { get }
init(page: Int, filters: Filters)
}
// Filterable protocol will eventually accept any types conforming to Filters and QueryParameters
protocol Filterable {
associatedtype F: Filters
associatedtype P: QueryParameters
func parameters() -> P
}
// This is your generic Transactions struct
// With this you will be able to pass other types that meet the constraints
struct Transactions<ParameterType: QueryParameters>: Filterable {
typealias P = ParameterType
typealias F = ParameterType.F
func parameters() -> ParameterType {
return P(page: 1, filters: F(isWithdrawal: true))
}
}
Run Code Online (Sandbox Code Playgroud)
你已经完成了通用的东西。现在您可以创建符合您的协议的不同模型对象
struct TransactionFilters: Filters {
private(set) var isWithdrawal: Bool // Conforming to filters
}
struct TransactionParameters<FilterType: Filters>: QueryParameters {
// Telling what type is the object that conforms to Filters
typealias F = FilterType
var page: Int
var filters: FilterType
init(page: Int, filters: Filters) {
self.page = page
self.filters = filters as! F
}
}
Run Code Online (Sandbox Code Playgroud)
像这样创建您的交易对象:
let transactions = Transactions<TransactionParameters<TransactionFilters>>()
print(transactions.parameters().page)
print(transactions.parameters().filters.isWithdrawal)
Run Code Online (Sandbox Code Playgroud)
您可以创建更多类型的查询参数和过滤器
struct SomeOtherParameters<FilterType: Filters>: QueryParameters {
// You can do custom stuff in your SomeOtherParameters struct
// e.g. add an offset to page
typealias F = FilterType
var page: Int
var filters: FilterType
init(page: Int, filters: Filters) {
self.page = page + 100
self.filters = filters as! F
}
}
// Your special filter that always returns false
struct SomeOtherFilters: Filters {
init(isWithdrawal: Bool) {}
var isWithdrawal: Bool {
return false
}
}
let transactionsWithDifferentFilters = Transactions<SomeOtherParameters<SomeOtherFilters>>()
// You can combine any types that conform to you declared protocols
let evenMoreTransactions = Transactions<SomeOtherParameters<TransactionFilters>>()
print(evenMoreTransactions.parameters().page)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12337 次 |
| 最近记录: |