一尘不染

类内部的变异函数

swift

考虑一下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关键字也能工作吗?


阅读 275

收藏
2020-07-07

共1个答案

一尘不染

语言指南-
方法中

从实例方法中修改值类型

结构和枚举是 类型。默认情况下,不能从其实例方法中修改值类型的属性。

但是,如果需要在特定方法中修改结构或枚举的属性,则可以选择对该方法进行行为更改。然后,该方法可以从方法内部更改(即更改)其属性,并在方法结束时将其所做的任何更改写回到原始结构。该方法还可以为其隐式self
属性分配一个全新的实例,并且该新实例将在方法结束时替换现有实例。

您可以通过将mutating关键字放在该方法的func关键字之前来选择这种行为…

因此,我们需要包含关键字mutating以允许
类型的成员(例如函数†)对其成员进行变异(例如a的成员属性)。对值类型实例的成员进行突变意味着对值类型实例本身()进行突变,而对 引用
类型实例的成员进行突变并不意味着对引用类型实例(被视为)的引用进行了突变。 struct``self self

因此,由于a
class是Swift中的引用类型,因此即使类中的实例成员或类发生突变,我们也无需mutatingZombie该类的任何实例方法中都包含关键字。如果我们要说的是改变实际的类实例fredTheZombie,我们将提到改变其实际
引用 (例如指向另一个Zombie实例)。

[†]:作为另一个示例,我们可以使用例如mutatinggetters(get);
在这种情况下,我们需要对此进行显式标记,因为nonmutating默认情况下是这些标记。set另一方面,Setters()是mutating默认设置,因此mutating即使它们使值类型的成员发生突变,也不需要关键字。

2020-07-07