Swift 词典的替代品<;字符串,任何>;?

Swift 词典的替代品<;字符串,任何>;?,swift,swift3,Swift,Swift3,我知道我的字典要么是,要么是,有没有办法在声明时告诉Swift编译器,而不是声明或 字典应该是 编辑:如果您的词典本身只能包含全部字符串s或全部编号s作为值,则类型应为或,这对您有帮助吗 func myFoo<T>(dic: [String: T]) { if dic["Key"] is String { print("The value is String --> \(dic["Key"])") } if dic["Key"] is

我知道我的字典要么是
,要么是
,有没有办法在声明时告诉Swift编译器,而不是声明

字典应该是


编辑:如果您的词典本身只能包含全部
字符串
s或全部
编号
s作为值,则类型应为
,这对您有帮助吗

func myFoo<T>(dic: [String: T]) {

    if dic["Key"] is String {
        print("The value is String --> \(dic["Key"])")
    }

    if dic["Key"] is Int {
        print("The value is Int --> \(dic["Key"])")
    }
}

myFoo(dic: ["Key": 0])
myFoo(dic: ["Key": "Value"])
func myFoo(dic:[字符串:T]){
如果dic[“键”]为字符串{
打印(“值为字符串-->\(dic[“键])”)
}
如果dic[“键”]为Int{
打印(“值为Int-->\(dic[“键])”)
}
}
myFoo(dic:[“键”:0])
myFoo(dic:[“键”:“值”])

user28434
的答案上展开,您可以模拟C联合类型的行为,因为它最适合“非此即彼”的情况,并且具有相互排斥的情况

但是,迅速实施工会可能看起来很丑陋:

enum StringOrNum {
    case a(String)
    case b(NSNumber)

    var a: String {
        switch(self)
        {
        case .a(let stringValue): return stringValue
        case .b(let nsnumberValue): return String(format:"%f", nsnumberValue.doubleValue)
        }
    }

    var b: NSNumber {
        switch(self)
        {
        case .a(let stringValue): if let intValue = Int(stringValue) {
                                      return NSNumber(value: intValue)
                                  }
                                  else {
                                      return NSNumber(value: 0)    // default case
                                  }
        case .b(let nsnumberValue): return nsnumberValue
        }
    }
}

然后将字典声明为
dictionary

您可以创建一个空协议,并使String和NSNumber符合它

protocol StringOrNumber {}

extension String:StringOrNumber {}
extension NSNumber:StringOrNumber {}
显式添加Int、Float和Double可能会有所帮助

extension Int:StringOrNumber {}
extension Float:StringOrNumber {}
extension Double:StringOrNumber {}
然后,您可以创建一个包含字符串和数字的字典

var dict:[String:StringOrNumber] = ["a":1, "b": 3.2,"c": "c"]

dict["d"] = "a string"
dict["e"] = 1.3 
但不能添加非字符串或数字的内容

dict["f"] = Date() //error: Cannot assign value of type 'Date' to type 'StringOrNumber?'

我想这就是为什么
Any
AnyObject
有帮助的原因。您是在声明函数参数
func f(a:[String:String]|[String:NSNumber])
,返回值
func f()->[String:String]|[String:NSNumber]
还是其他什么?
[String:Any
是一种方法,也许声明generic会有所帮助,但我认为它对函数param更有用,因为它们可以接受协议。如果可能的话,我想使用一些更具体的声明……问题是他仍然不能声明
var stringOrNumberDict:[String:other]=[“A”:1,“B”:“two”]
他必须使用
[“A”:other(1),“B”:任意(“两个”)]
。不过,很努力@Grimxn,为什么要隐藏
init?(:Any)
?当您有一个
[Any]
字符串
/
并且您
将其映射到
上以获得任意-enum.OK的数组时,就是这种情况。为了纯洁!但是,如果需要使用带有
[Any]
的init,那么就使用它吧!或者从任何(:[Any])->[其中一个]
创建工厂
静态函数。如果可能的话,我会试图从我的接口中隐藏可失败的初始化…@Grimxn,你能详细说明一下吗?在
(Any)->T?
函数中有什么危险?尽管有
[Any]
的情况(这是对基本结构的扩展),但failable init是一个内部机制,它只能(由您的公共init)用
L
R
调用,因此永远不会真正失败。通过将其公开,您可以让其他开发人员完全使用另一种类型来调用它-这是他们的问题,当然不是您的问题-但这只是给了另一个错误使用强制展开的机会(天知道我们在这里看到的已经够多了!)
var dict:[String:StringOrNumber] = ["a":1, "b": 3.2,"c": "c"]

dict["d"] = "a string"
dict["e"] = 1.3 
dict["f"] = Date() //error: Cannot assign value of type 'Date' to type 'StringOrNumber?'