如何扩展Swift Dictionary中的K:String和V:String

Ila*_*evy 6 generics ios swift

我在考虑以下语法:

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

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

use*_*734 9

这应该够了......

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] = [:]
Run Code Online (Sandbox Code Playgroud)

不要使其他类型符合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")
Run Code Online (Sandbox Code Playgroud)


R M*_*nke 5

不可能以你想要的方式去做.只能限制extensionsDictionaryprotocols 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")
Run Code Online (Sandbox Code Playgroud)

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

  • 仅允许此功能 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")
Run Code Online (Sandbox Code Playgroud)

虽然这个功能可以在任何工作Dictionary,其ValueEquatable,你可以选择只使用它在那些有String作为Value


如果你真的需要它只能工作,String你需要创建一个自定义protocol,只有String符合它.在protocol将需要有一个返回计算的属性self,因为否则你将不能够print它,因为它不被认为是String内部的extension.

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") 
Run Code Online (Sandbox Code Playgroud)

边注:

既然Dictionary是一个struct功能必须mutating以改变self.

  • @EridB因为`StringLiteralConvertible`没有将函数约束为`String` (2认同)