【问题标题】:how to extend Swift Dictionary of where K:String and V:String如何扩展 K:String 和 V:String 的 Swift 字典
【发布时间】:2016-03-05 12:04:31
【问题描述】:

我在想下面的语法:

extension Dictionary where Key:String,Value:String{
    func addIfNew(key:String,value:String){
      print("new item added: \(key) with value: \(value)")
    }
}

例如:该函数将记录任何新添加的数据

【问题讨论】:

    标签: ios swift generics


    【解决方案1】:

    这就够了……

    protocol P {}
    extension String: P {}
    extension Dictionary where Key:P, Value:P {
        func addIfNew(key:String, value:String){
            print("new item added: \(key) with value: \(value)")
        }
    }
    
    let d:[String:String] = [:]
    

    别做其他符合P的类型就好了

    在 Swift3 中

    extension Dictionary where Key == String, Value == String {
        func addIfNew(key:String, value:String){
            print("new item added: \(key) with value: \(value)")
        }
    }
    let d:[String:String] = [:]
    d.addIfNew(key: "a", value: "A")
    

    【讨论】:

    • keyvalue 应该是 KeyValue 类型,但除此之外,如果它有效,那就太好了!它与我的StringType 没有什么不同,只是StringTypeP 更具表现力
    • @RMenke 的诀窍是将键和值参数定义为字符串类型。如果您尝试使用其他方法调用该函数,编译器会抱怨。因此,按照我自己的意思,如果您想在键值对需要精确类型时进行扩展,这是最好的方法。
    【解决方案2】:

    不可能按照您想要的方式进行。您也只能将Dictionaryextensions 约束为protocols Key 和/或Value。否则你只会得到更多的错误。

    但你可以这样做:

    extension String : CustomStringConvertible {
    
        public var description : String { return self }
    
    }
    
    extension Dictionary where Key : CustomStringConvertible, Value : CustomStringConvertible {
        func addIfNew(key:Key,value:Value){
            print("new item added: \(key.description) with value: \(value.description)")
        }
    }
    
    var dict : [String:String] = [:]
    dict["blah"] = "foo"
    dict.addIfNew("blah", value: "foo2")
    

    重要的是问问自己你想要什么。

    • 仅在Strings 上允许此功能
    • Equatable 的任何内容都足够好

    如果Equatable 足够好,您可以这样做:

    extension Dictionary where Value : Equatable {
        mutating func addIfNew(key:Key,value:Value){
    
            if self.values.contains(value) {
                print("\(value) exists")
            } else {
                print("new item added: \(key) with value: \(value)")
                self[key] = value
            }
        }
    }
    
    var dict : [String:String] = [:]
    dict["blah"] = "foo"
    dict.addIfNew("blah1", value: "foo2")
    dict.addIfNew("blah2", value: "foo2")
    

    虽然此功能适用于ValueEquatable 的任何Dictionary,但您可以选择仅对StringValueValue 使用它


    如果你真的需要它只在String 上工作,你需要创建一个自定义protocol 并且只有String 符合它。 protocol 需要有一个返回 self 的计算属性,因为否则您将无法 print 它,因为它在 extension 中不被视为 String

    protocol StringType : Hashable {
    
        var value : String { get }
    
    }
    
    extension String : StringType {
    
        var value : String { return self }
    
    }
    
    extension Dictionary where Key : StringType, Value : StringType {
        mutating func addIfNew(key:Key,value:Value){
    
            if self.values.contains(value) {
                print("\(value.value) exists")
            } else {
                print("new item added: \(key.value) with value: \(value.value)")
                self[key] = value
            }
        }
    }
    
    var dict : [String:String] = [:]
    dict["blah"] = "foo"
    dict.addIfNew("blah1", value: "foo2")
    dict.addIfNew("blah2", value: "foo2") 
    

    旁注:

    由于Dictionarystruct,函数需要mutating 才能更改self

    【讨论】:

    • 为什么不直接使用StringLiteralConvertible 而不是自定义协议?
    • @EridB 因为StringLiteralConvertible 不将函数限制为仅String
    • 如果您在答案中提供更多类似这样的信息可能会很棒,同时还解释了变异功能,同时考虑到其他会来看这个问题的用户。除此之外,这是一个很好的答案+1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    相关资源
    最近更新 更多