我想分层存储值,以便我可以用点表示法轻松访问它们:
my.node = "n"
my.node.a = "a1"
my.node.b = "b1"
my.node.b.x = "x2"
所以基本上在编写没有点的my.node时,我想得到一个字符串,但是在编写my.node.a时,它应该返回一个数组/ class / struct / ..,它具有属性a。
结构将定义一次,因此它可能有点混乱或复杂,但它将在整个应用程序中广泛使用,所以我想避免使用大量的数组括号或类似的丑陋构造。
有可能吗?
答案 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
来获取字符串。