我在 Swift 中喝了 struct/value koolaid。现在我有一个有趣的问题,我不知道如何解决。我有一个结构,它是一个容器,例如
struct Foo {
var bars:[Bar]
}
当我对此进行编辑时,我会创建副本以便保留撤消堆栈。到目前为止,一切都很好。就像好的教程显示的那样。不过,我对这个人使用了一些派生属性:
struct Foo {
var bars:[Bar]
var derivedValue:Int {
...
}
}
在最近的分析中,我注意到 a) 计算 derivedValue 的计算有点昂贵/冗余 b) 在各种用例中并不总是需要计算。
以我经典的 OOP 方式,我会将其设为记忆/惰性变量。基本上,在调用之前让它为零,计算一次并存储它,并在以后的调用中返回所述结果。由于我遵循“制作副本以进行编辑”模式,因此不会破坏不变量。
但是如果它是结构,我不知道如何应用这种模式。我可以做这个:
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
}
这有效,直到结构引用该值本身,例如
struct Foo {
var bars:[Bar]
lazy var derivedValue:Int = self.computeDerivation()
fun anotherDerivedComputation() {
return self.derivedValue / 2
}
}
此时,编译器会抱怨,因为anotherDerivedComputation
正在导致接收器发生更改,因此需要标记mutating
。将访问器标记为变异是错误的。但是为了咧嘴笑,我尝试了一下,但这会产生一系列新的问题。现在任何地方我都有这样的表达
XCTAssertEqaul(foo.anotherDerivedComputation(), 20)
编译器抱怨是因为参数隐式是非可变的 let 值,而不是 var。
有一个带有延迟/延迟/缓存成员的结构,我是否缺少一种模式?