我在Swift中缺少关于可变性概念的东西。我通常使用对象而不是结构来获得可观察性,因此值语义对我来说仍然是新的。
struct Game {
var map: [[Int]]
所以在这里,我宣布map
为可变的。那么为什么要使用这种方法...
mutating func createPlayer() {
// emptyLocation -> (Int, Int)
let (X,Y) = emptyLocation()
map[X][Y] = .player
}
...我必须使用变异吗?是的,该函数正在变异,但是原始的结构是这样声明的。实际上,实际上每个func
都会是mutating
,这似乎违反了标记的目的。
还有其他方法可以执行此操作吗? mutating
的常用用法是否表示我应该避免的性能/内存问题?
更新:我对结构的内部状态“泄漏”到周围代码的方式感到不安;如果在结构内部声明成员var
,则即使您从未更改,它也必须在结构外部。这违反了我能想到的每个封装概念。因此,我将struct
更改为class
,删除了所有mutating
并完成了操作。我知道了,但是我不确定我是否完全理解实现。在这个Swift-noob看来,mutating
是编译器可以在不通知我的情况下确定的-成员是否声明为var
?func实际上会对其进行突变吗?等
答案 0 :(得分:2)
是的,struct
或enum
的默认行为是实例方法不能修改属性,因为它们是值类型。因此,您需要使用mutating
覆盖此行为。
定义属性var或let的方式仍然与是否可以从可变实例方法更改或直接更改它无关。
由于您的财产不是私人财产,您仍然可以这样做
var g = Game(map: [[1]])
g.map.append([2])
答案 1 :(得分:0)
在Swift中,结构具有值语义,即,即使出于性能原因将它们String
和Array
之类的某些对象实现为引用,也可以将它们视为值。如果您不是该结构的唯一所有者,则在对这样的结构进行突变时,编译器实际上可能必须进行复制。这就是所谓的写时复制,这是变异指示的可能的性能问题。