为什么这个 Swift 结构需要 "mutating"?
Why does this Swift struct require "mutating"?
我在 Swift 中遗漏了一些关于可变性概念的内容。我通常使用对象而不是结构来获得可观察性,因此值语义对我来说仍然是新的。
struct Game {
var map: [[Int]]
所以我在这里声明 map
是可变的。那么为什么在这样的方法中...
mutating func createPlayer() {
// emptyLocation -> (Int, Int)
let (X,Y) = emptyLocation()
map[X][Y] = .player
}
...我必须使用变异吗?是的,该函数正在发生变化,但原始结构是这样声明的。似乎实际上每个 func
都会 mutating
实际上,这似乎违背了标记的目的。
有没有其他方法可以做到这一点? mutating
的常见用法是否表明我应该避免 performance/memory 问题?
更新: 我对结构 "leaked out" 的内部状态到周围代码的方式感到相当不安;如果你在结构内部声明一个成员 var
那么它也必须在外部,即使你从未改变过。这违反了我能想到的每一个封装概念。所以我将 struct
更改为 class
,删除了所有 mutating
,并完成了它。我明白了,但我不确定我是否完全理解实现。对于这个 Swift-noob 来说,mutating
似乎是编译器可以在我不告诉它的情况下确定的东西 - 成员声明为 var
吗?函数是否真的改变了它?等等
是的,struct
或 enum
的默认行为是实例方法不能修改 属性,因为它们是值类型。所以你需要使用 mutating
来覆盖这个行为。
您定义 属性 var 或 let 的方式仍然与是否可以从可变实例方法或直接更改它有关。
由于您的属性不是私人的,您仍然可以
var g = Game(map: [[1]])
g.map.append([2])
在 Swift 中,结构具有值语义,即它们的行为就好像它们是值,即使其中一些像 String
和 Array
出于性能原因被实现为引用。当您改变这样的结构时,如果您不是该结构的唯一所有者,编译器实际上可能必须制作一个副本;这被称为写入时复制,这是变异指示的可能的性能问题。
我在 Swift 中遗漏了一些关于可变性概念的内容。我通常使用对象而不是结构来获得可观察性,因此值语义对我来说仍然是新的。
struct Game {
var map: [[Int]]
所以我在这里声明 map
是可变的。那么为什么在这样的方法中...
mutating func createPlayer() {
// emptyLocation -> (Int, Int)
let (X,Y) = emptyLocation()
map[X][Y] = .player
}
...我必须使用变异吗?是的,该函数正在发生变化,但原始结构是这样声明的。似乎实际上每个 func
都会 mutating
实际上,这似乎违背了标记的目的。
有没有其他方法可以做到这一点? mutating
的常见用法是否表明我应该避免 performance/memory 问题?
更新: 我对结构 "leaked out" 的内部状态到周围代码的方式感到相当不安;如果你在结构内部声明一个成员 var
那么它也必须在外部,即使你从未改变过。这违反了我能想到的每一个封装概念。所以我将 struct
更改为 class
,删除了所有 mutating
,并完成了它。我明白了,但我不确定我是否完全理解实现。对于这个 Swift-noob 来说,mutating
似乎是编译器可以在我不告诉它的情况下确定的东西 - 成员声明为 var
吗?函数是否真的改变了它?等等
是的,struct
或 enum
的默认行为是实例方法不能修改 属性,因为它们是值类型。所以你需要使用 mutating
来覆盖这个行为。
您定义 属性 var 或 let 的方式仍然与是否可以从可变实例方法或直接更改它有关。
由于您的属性不是私人的,您仍然可以
var g = Game(map: [[1]])
g.map.append([2])
在 Swift 中,结构具有值语义,即它们的行为就好像它们是值,即使其中一些像 String
和 Array
出于性能原因被实现为引用。当您改变这样的结构时,如果您不是该结构的唯一所有者,编译器实际上可能必须制作一个副本;这被称为写入时复制,这是变异指示的可能的性能问题。