首页 > 解决方案 > 快速泛型中的 OR 子句

问题描述

所以,我正在尝试从头开始编写一个网络库,并且我正在尝试利用泛型。

我正在使用 URLComponents 生成 URL

我的 URLComponent 扩展看起来像这样

 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)
            }
        }
    }

这是我的参数结构

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 被多次重载,具有相同的主体,因为 Argument 的 Type T 不同。我需要想办法摆脱这种混乱。

我想是否有办法在 where 子句中包含 OR 逻辑,但没有这样的方法。

如何改进此逻辑并删除冗余代码?

标签: iosxcodegenericsswift5

解决方案


在这种情况下,泛型是错误的方法。

泛型类型的共同点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{$0.description}.joined(separator: "-")
        } else {
            return valueName.description
        }
    }
}

推荐阅读