swift 泛型中的 OR 子句
OR clause in swift generics
所以,我正在尝试从头开始编写一个网络库,并且我正在尝试利用泛型。
我正在使用 URL组件生成 URL
我的URL组件扩展看起来像这样
extension URLComponents {
/*mutating func setQueryItems(params : [Argument<Any>]){
let q = params.map{ item in
if let value = item.valueName.getValue {
URLQueryItem(name: item.keyName, value: value)
}
}
self.populateQueryItems(queryItems: q)
}*/
mutating func setQueryItems(params : [Argument<Bool>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.getValue)
}
self.populateQueryItems(queryItems: q)
}
mutating func setQueryItems(params : [Argument<Double>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.getValue)
}
self.populateQueryItems(queryItems: q)
}
mutating func setQueryItems(params : [Argument<String>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.valueName)
}
self.populateQueryItems(queryItems: q)
}
mutating private func populateQueryItems(queryItems : [URLQueryItem]){
if self.queryItems == nil {
self.queryItems = queryItems
}else {
self.queryItems?.append(contentsOf: queryItems)
}
}
}
这是我的 Argument 结构
struct Argument<T> {
var keyName : String
var valueName : T
}
extension Argument where T == Int {
var getValue : String{
return valueName.description
}
}
extension Argument where T == Double {
var getValue : String{
return valueName.description
}
}
extension Argument where T == Bool {
var getValue : String{
return valueName.description
}
}
如您所见,在 URLComponent 的扩展中,函数 setQueryItems 被多次重载,具有相同的主体,因为参数的类型 T 不同。我需要想办法摆脱这个烂摊子。
我想是否有办法在 where 子句中包含 OR 逻辑,但没有这样的方法。
如何改进此逻辑并删除冗余代码?
在这种情况下,泛型是错误的方法。
Argument
泛型的共同点是协议CustomStringConvertible
,所有采用协议的类型都有一个description
属性.
声明结构非泛型
struct Argument {
var keyName : String
var valueName : CustomStringConvertible
var value : String { return valueName.description }
}
并且 URLComponents
扩展可以减少到
extension URLComponents {
mutating func setQueryItems(params : [Argument]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.value)
}
self.populateQueryItems(queryItems: q)
}
mutating private func populateQueryItems(queryItems : [URLQueryItem]){
if self.queryItems == nil {
self.queryItems = queryItems
}else {
self.queryItems?.append(contentsOf: queryItems)
}
}
}
编辑:
如果你还想考虑数组,你必须扩展 value
属性 例如
struct Argument {
var keyName : String
var valueName : CustomStringConvertible
var value : String {
if let valueArray = valueName as? [CustomStringConvertible] {
return valueArray.map{[=12=].description}.joined(separator: "-")
} else {
return valueName.description
}
}
}
所以,我正在尝试从头开始编写一个网络库,并且我正在尝试利用泛型。
我正在使用 URL组件生成 URL
我的URL组件扩展看起来像这样
extension URLComponents {
/*mutating func setQueryItems(params : [Argument<Any>]){
let q = params.map{ item in
if let value = item.valueName.getValue {
URLQueryItem(name: item.keyName, value: value)
}
}
self.populateQueryItems(queryItems: q)
}*/
mutating func setQueryItems(params : [Argument<Bool>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.getValue)
}
self.populateQueryItems(queryItems: q)
}
mutating func setQueryItems(params : [Argument<Double>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.getValue)
}
self.populateQueryItems(queryItems: q)
}
mutating func setQueryItems(params : [Argument<String>]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.valueName)
}
self.populateQueryItems(queryItems: q)
}
mutating private func populateQueryItems(queryItems : [URLQueryItem]){
if self.queryItems == nil {
self.queryItems = queryItems
}else {
self.queryItems?.append(contentsOf: queryItems)
}
}
}
这是我的 Argument 结构
struct Argument<T> {
var keyName : String
var valueName : T
}
extension Argument where T == Int {
var getValue : String{
return valueName.description
}
}
extension Argument where T == Double {
var getValue : String{
return valueName.description
}
}
extension Argument where T == Bool {
var getValue : String{
return valueName.description
}
}
如您所见,在 URLComponent 的扩展中,函数 setQueryItems 被多次重载,具有相同的主体,因为参数的类型 T 不同。我需要想办法摆脱这个烂摊子。
我想是否有办法在 where 子句中包含 OR 逻辑,但没有这样的方法。
如何改进此逻辑并删除冗余代码?
在这种情况下,泛型是错误的方法。
Argument
泛型的共同点是协议CustomStringConvertible
,所有采用协议的类型都有一个description
属性.
声明结构非泛型
struct Argument {
var keyName : String
var valueName : CustomStringConvertible
var value : String { return valueName.description }
}
并且 URLComponents
扩展可以减少到
extension URLComponents {
mutating func setQueryItems(params : [Argument]){
let q = params.map{ item in
URLQueryItem(name: item.keyName, value: item.value)
}
self.populateQueryItems(queryItems: q)
}
mutating private func populateQueryItems(queryItems : [URLQueryItem]){
if self.queryItems == nil {
self.queryItems = queryItems
}else {
self.queryItems?.append(contentsOf: queryItems)
}
}
}
编辑:
如果你还想考虑数组,你必须扩展 value
属性 例如
struct Argument {
var keyName : String
var valueName : CustomStringConvertible
var value : String {
if let valueArray = valueName as? [CustomStringConvertible] {
return valueArray.map{[=12=].description}.joined(separator: "-")
} else {
return valueName.description
}
}
}