在Swift中是否可以以相同的名称存储String和Array?

时间:2015-03-05 13:51:24

标签: 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。

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

有可能吗?

2 个答案:

答案 0 :(得分:2)

my.node.a = "a1"
my.node.b = "b1"

问题是你在这里建议使用点符号。这是一个内置的Swift语法;你没有重新定义它。因此,除非my是具有实例属性node的类的实例,否则您不能这样说话,node是具有实例属性a和{的类的实例{1}}。 ex hypothesi 他们不是。

换句话说,您当然可以执行您想要执行的操作(构建节点层次结构),但无法使用您描述的语法来获取它们的值。这不是Ruby(或类似的),你可以干涉消息发送机制。

所以,我在你所描述的那种层次结构中的第一次切割看起来像这样(你会立刻看到我正在使用你不想使用的那种符号!):

b

我可以为您做的是消除class Thing { var val : String var d = [String:Thing]() init(_ val:String) {self.val = val} subscript(key:String) -> Thing { return self.d[key]! } } let my = Thing("n") let a = Thing("a1") let b = Thing("b1") let x = Thing("x2") b.d["x"] = x my.d["a"] = a my.d["b"] = b let result1 = my.val let result2 = my["a"].val let result3 = my["b"].val let result4 = my["b"]["x"].val 的双重下标。为此,我们需要重新发明密钥路径。 (我说“重新发明”,因为NSObject已经有了这个。)因此,如果我们像这样定义Thing:

["b"]["x"]

现在我们可以像这样编写最后一次获取:

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

您可以肯定,您的原始问题是关于设置,而不是获取。你可以用下标setter做类似的事情,但是我把这个留给你来计算细节,因为原来的问题没有以允许我理解确切规范的方式制定。

答案 1 :(得分:0)

由于无法重载默认赋值运算符(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html),并且在Swift(Does Swift support implicit conversion?)中也不允许隐式类型转换,我担心你可以' t准确得到你想要的行为。 一种解决方案可能看起来像这样:

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

value显然属于您想要的任何类型。它仍然需要.description来获取字符串。