考虑一下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 } }
僵尸继承了Monster类的名称字段。
var name = "Monster"
为什么
fredTheZombie.changeName("Tom", walksWithLimp: true)
即使在函数头之前没有mutation关键字也能工作吗?
从语言指南- 方法中:
从实例方法中修改值类型 结构和枚举是 值 类型。默认情况下,不能从其实例方法中修改值类型的属性。 但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择对该方法进行行为更改。然后,该方法可以从方法内部更改(即更改)其属性,并在方法结束时将其所做的任何更改写回到原始结构。该方法还可以为其隐式self 属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。 您可以通过将mutating关键字放在该方法的func关键字之前来选择这种行为…
从实例方法中修改值类型
结构和枚举是 值 类型。默认情况下,不能从其实例方法中修改值类型的属性。
但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择对该方法进行行为更改。然后,该方法可以从方法内部更改(即更改)其属性,并在方法结束时将其所做的任何更改写回到原始结构。该方法还可以为其隐式self 属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。
self
您可以通过将mutating关键字放在该方法的func关键字之前来选择这种行为…
mutating
因此,我们需要包含关键字mutating以允许 值 类型的成员(例如函数†)对其成员进行变异(例如a的成员属性)。对值类型实例的成员进行突变意味着对值类型实例本身()进行突变,而对 引用 类型实例的成员进行突变并不意味着对引用类型实例(被视为)的引用进行了突变。 struct``self self
struct``self
因此,由于a class是Swift中的引用类型,因此即使类中的实例成员或类发生突变,我们也无需mutating在Zombie该类的任何实例方法中都包含关键字。如果我们要说的是改变实际的类实例fredTheZombie,我们将提到改变其实际 引用 (例如指向另一个Zombie实例)。
class
Zombie
fredTheZombie
[†]:作为另一个示例,我们可以使用例如mutatinggetters(get); 在这种情况下,我们需要对此进行显式标记,因为nonmutating默认情况下是这些标记。set另一方面,Setters()是mutating默认设置,因此mutating即使它们使值类型的成员发生突变,也不需要关键字。
get
nonmutating
set