在Swift中是否可以以相同的名称存储字符串和数组?

在Swift中是否可以以相同的名称存储字符串和数组?,swift,Swift,我希望按层次存储值,以便以点表示法轻松访问它们: my.node = "n" my.node.a = "a1" my.node.b = "b1" my.node.b.x = "x2" 因此,基本上,在编写没有点的my.node时,我希望得到一个字符串,但在编写my.node.a时,它应该返回一个数组/class/struct/,该数组具有属性a 该结构将被定义一次,因此可能有点混乱或复杂,但它将在整个应用程序中广泛使用,因此我希望避免大量的数组括号或类似丑陋的构造 有可能吗?由于无法重载默认赋

我希望按层次存储值,以便以点表示法轻松访问它们:

my.node = "n"
my.node.a = "a1"
my.node.b = "b1"
my.node.b.x = "x2"
因此,基本上,在编写没有点的my.node时,我希望得到一个字符串,但在编写my.node.a时,它应该返回一个数组/class/struct/,该数组具有属性a

该结构将被定义一次,因此可能有点混乱或复杂,但它将在整个应用程序中广泛使用,因此我希望避免大量的数组括号或类似丑陋的构造


有可能吗?

由于无法重载默认赋值运算符(),而且Swift()中也不允许隐式类型转换,因此您恐怕无法准确获得所需的行为。 一种解决方案可能是这样的:

struct Test : StringLiteralConvertible, Printable
{
    private var name = ""
    var value : Int = 0

    init(name n:String)
    {
        name = n
    }

    init(stringLiteral value: StringLiteralType)
    {
        self.init(name: value)
    }

    init(extendedGraphemeClusterLiteral value: String)
    {
        self.init(name: value)
    }

    init(unicodeScalarLiteral value: String)
    {
        self.init(name: value)
    }

    var description: String
    {
        get { return name }
    }
}
带有
显然是您想要的任何类型。它仍然需要
.description
来获取字符串

my.node.a = "a1"
my.node.b = "b1"
问题是,这里您建议使用点表示法。这是一个内置的Swift语法;你不需要重新定义它。因此,除非
my
是具有实例属性
node
的类的实例,
node
是具有实例属性
a
b
的类的实例,否则您不能这样说话。假设他们不是

换句话说,您当然可以做您想做的事情(构建节点的层次结构),但不能使用您描述的语法获取它们的值。这不是Ruby(或类似的)可以干扰消息发送机制的地方

因此,我对你描述的层次结构的第一个切入点是这样的(你马上就会看到我使用的正是你不喜欢使用的那种符号!):

我能为您做的是消除双重订阅
[“b”][“x”]
。为此,我们需要重新设计关键路径。(我说“重新发明”是因为NSObject已经有了这一点。)因此,如果我们这样定义事物:

class Thing {
    var val : String
    var d = [String:Thing]()
    init(_ val:String) {self.val = val}
    subscript(key:String) -> Thing {
        let path = split(key, {$0=="."}, maxSplit: 1)
        if path.count == 2 {
            return self.d[path[0]]![path[1]]
        }
        return self.d[key]!
    }
}
let result4 = my["b.x"].val
现在我们可以这样编写最后一次获取:

class Thing {
    var val : String
    var d = [String:Thing]()
    init(_ val:String) {self.val = val}
    subscript(key:String) -> Thing {
        let path = split(key, {$0=="."}, maxSplit: 1)
        if path.count == 2 {
            return self.d[path[0]]![path[1]]
        }
        return self.d[key]!
    }
}
let result4 = my["b.x"].val
您可以很容易地看到,如果这是一个由五个或十个节点组成的链,那么至少可以节省大量的符号:

let my = Thing("n")
let b = Thing("b1")
let x = Thing("x2")
let y = Thing("y3")
let z = Thing("z4")

y.d["z"] = z
x.d["y"] = y
b.d["x"] = x
my.d["b"] = b

let result = my["b.x.y.z"].val // better than nothing...
好的-但这样做之后,我可以在每次提取结束时消除不需要的
.val
,从而完成您最初要求完成的事情

class Thing {
    var val : String
    var d = [String:Thing]()
    init(_ val:String) {self.val = val}
    subscript(key:String) -> String {
        let path = split(key, {$0=="."}, maxSplit: 1)
        if path.count == 2 {
            return self.d[path[0]]![path[1]]
        }
        return self.d[key]!.val
    }
}

let my = Thing("n")
let b = Thing("b1")
let x = Thing("x2")
let y = Thing("y3")
let z = Thing("z4")

y.d["z"] = z
x.d["y"] = y
b.d["x"] = x
my.d["b"] = b

let result1 = my["b"]
let result2 = my["b.x.y.z"]

当然,你最初的问题是关于设置,而不是获取。您可以对下标设置器执行类似的操作,但我将此留给您来解决细节问题,因为原始问题的表述方式不允许我理解确切的规范是什么。

您可以将节点设置为结构。等等。是的,但是当我只使用结构而不访问成员时,它能返回字符串吗?比如:my.node返回“n”?如果是,请您提供一个简单的例子好吗?感谢您的解释,这与我们试图实现的目标非常接近,但有一个问题:让result=my[“b.x.y.z”]。val将允许您在字符串中引入拼写错误。因此,我们的想法是创建一个大对象my(或api),不管它有多复杂(分配的复杂性并不重要),并将所有不同的值作为真实的成员,比如my.b.x.y.z。但是我们不能同时为my.b和my.b.x设置字符串值,这就是问题所在。这是一个崇高的目标,@sigma,但我要说的是你不能这样做。我在回答的开头解释了原因。你可以在Ruby中实现这一点,因为你可以向任意对象发送任意消息(duck类型)并在它到达时处理它,但不能在Swift中实现这一点,Swift的消息发送理念正好相反(严格类型)。是的,我们必须混合使用最佳近似值。谢谢你抽出时间!这并不是说要输入不同的值,而是要输出不同的值。不管怎样,可打印的看起来很有趣,谢谢!