在以下情况下,我尝试编写更少的代码:
我有这个Queryable
协议和一个Parameter
枚举:
protocol Queryable {
var urlQuery: URLQueryItem { get }
}
enum PaginationParameter: Queryable {
case page(Int)
case pageSize(Int)
var queryItem: URLQueryItem {
switch self {
case .page(let page):
return URLQueryItem(name: "page", value: page.description)
case .pageSize(let pageSize):
return URLQueryItem(name: "page_size", value: pageSize.description)
}
}
}
还有一个枚举,它提供了一些默认情况和一些由通用类型定义的特定情况:
enum Parameter<P: Queryable> {
case pagination(PaginationParameter)
case specific(P)
}
enum BookParameters: Queryable {
case search(String)
case id(Int)
var urlQuery: URLQueryItem {
switch self {
case .search(let string):
return URLQueryItem(name: "search", value: string)
case .id(let id):
return URLQueryItem(name: "id", value: id.description)
}
}
}
let parameters: [Parameter<BookParameters>] = [
.pagination(.pageSize(10)),
.specific(.id(123))
]
现在,我需要通过.pagination
和.specific
两种情况来获取url查询项。
let queryItems = parameters.map({
switch $0 {
case .pagination(let param):
return param.queryItem
case .specific(let param):
return param.queryItem
}
})
最好有一种方法来处理组合在一起的嵌套案例,因为它们遵循相同的协议。这是行不通的,因为我必须遍历父案例的嵌套案例:
一个小改进是将switch语句埋入Parameters枚举的扩展中,并使它也符合Queryable
协议:
extension Parameters: Queryable {
let queryItem: URLQueryItem {
switch self {
case .pagination(let param):
return param.queryItem
case .specific(let param):
return param.queryItem
}
}
}
这导致了一个班轮,但我只是将问题转移到了另一个地方。
let queryItems = parameters.map({ $0.queryItem })
答案 0 :(得分:2)
由于您正在使用带有关联值的嵌套枚举,因此我真的没有办法避免在顶级Parameter
枚举上进行此额外的切换。就我而言,Swift并没有为我们提供一种工具来处理案例,因为我们无法将具有“相同”关联值类型的所有案例转换为单个案例。您可以做的是重新考虑Parameter
类型的存在,因为由于您仍然需要将其称为Parameter<BookParameters>
或Parameter<SomeOtherTypeThatConformsToQueryable>
的事实,它似乎并没有真正的用处。
我个人会跳过顶级枚举,直接将parameters
属性类型称为[Queryable]
。
var parameters: [Queryable] = [
PaginationParameter.pageSize(10),
BookParameters.id(123)
]
使事情变得更加简单和容易。现在,还有一种方法可以添加其他类型的其他案例,而您的初始解决方案是不可能的。
enum SomeOtherTypeThatConformsToQueryable: Queryable {
case aVeryNiceCase(Int)
}
parameters.append(SomeOtherTypeThatConformsToQueryable.aVeryNiceCase(0))
// Appending this to array of type `[Parameter<BookParameters>]`, would not be
// possible without explicitly adding new case to the `Parameter` enumeration
如果您发现自己经常打电话给map { $0.queryItem }
,则可以提供Array
的扩展名,其中Element
是Queryable
的类型
extension Array where Element==Queryable {
var queryItems: [URLQueryItem] { return map { $0.queryItem } }
}
// And now you can simply call
let queryItems = parameters.queryItems
答案 1 :(得分:1)
如果不使Parameters
符合Queryable
,则只需在Parameters
中引入变量来获取queryItem
,因为两种情况都接受已经符合{{1 }},
Queryable