在Swift中考虑这个类:
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown()
{
town?.changePopulation(-10)
super.terrorizeTown()
}
func changeName(name: String, walksWithLimp: Bool)
{
self.name = name
self.walksWithLimp = walksWithLimp
}
}
Zombie继承了Monster类的名字字段。
var name = "Monster"
为什么
fredTheZombie.changeName("Tom", walksWithLimp: true)
即使函数头之前没有变异关键字,也可以工作吗?
答案 0 :(得分:15)
来自The Language Guide - Methods:
从实例方法中修改值类型
结构和枚举是 value 类型。默认情况下 无法在其实例中修改值类型的属性 方法
但是,如果您需要修改结构的属性或 在特定方法中枚举,您可以选择进行变异 该方法的行为。然后该方法可以变异(即更改) 它在方法中的属性,以及它所做的任何更改 当方法结束时,将写回原始结构。该 方法还可以为其隐式
self
分配一个全新的实例 属性,这个新实例将替换现有的实例 方法结束。您可以通过放置
mutating
关键字来选择此行为 该方法的func关键字......
因此,我们需要包含关键字mutating
以允许值类型的成员(例如函数†)来改变其成员(例如struct
)的成员属性。改变值类型实例的成员意味着改变值类型实例本身(self
),而改变引用类型实例的成员并不意味着引用类型实例的引用(这被认为是self
)被改变了。
因此,由于class
是Swift中的引用类型,我们不需要在mutating
类的任何实例方法中包含Zombie
关键字,即使它们改变了实例成员或类。如果我们要谈论改变实际的类实例fredTheZombie
,我们会提到改变它的实际引用(例如指向另一个Zombie
实例)。
[†]:作为另一个例子,我们可以使用例如mutating
getters(get
);在这种情况下,我们需要明确标记,因为默认情况下这些是nonmutating
。另一方面,Setters(set
)默认为mutating
,因此即使它们改变了值类型的成员,也不需要mutating
关键字。
答案 1 :(得分:6)
mutating
与类无关,只适用于值类型,例如struct
和enum
答案 2 :(得分:2)
不改变func
struct Counter {
let count: Int
init(count: Int = 0) {
self.count = count
}
// the functional approach
func counterByIncrementing() -> Counter {
let newCount = count + 1
return Counter(count: newCount)
}
}
var counter = Counter()
counter = counter.counterByIncrementing()
变异功能
struct Counter {
// this now has to be a var :/
var count: Int
init(count: Int = 0) {
self.count = count
}
// the mutating keyword approach
mutating func increment() {
count += 1
}
}
var counter = Counter()
counter.increment()
在课堂上,所有的功能都在变异。但是对于struct和enum,我们需要指定。
答案 3 :(得分:2)
另一个易于理解的例子,在 Swift 3& 4 强>
struct City
{
var population : Int
func changePopulation(newpopulation : Int) {
population = newpopulation //error: cannot modify property "population"
}
}
var mycity = City(population : 500)
mycity.changePopulation(newpopulation : 2000) //error: cannot modify property "population"
<强> 解决方案 强>
mutating func changePopulation(newpopulation : Int)