【问题标题】:Mutating function inside class类内的变异函数
【发布时间】:2016-11-20 05:43:11
【问题描述】:

考虑一下 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 类的 name 字段。

var name = "Monster"

为什么

fredTheZombie.changeName("Tom", walksWithLimp: true) 

即使函数头之前没有 mutating 关键字也能工作?

【问题讨论】:

  • A class 是 Swift 中的引用类型。因此,改变 类实例 fredTheZombie 将意味着改变它的实际引用。另一方面,改变它的包装成员不被视为改变类实例本身。因此在这种情况下不需要mutating 关键字。
  • 我已经读过,为了更改类中变量的值(在实例方法内),您必须声明函数变异。我还没有这样做...
  • 这是一个适用于改变值类型成员的规则(例如struct的成员属性)。改变值类型的成员意味着改变值类型本身(self),而改变引用类型的成员并不意味着改变引用类型的引用(被认为是self)。
  • 乐于助人。有关更多详细信息,请参阅The Language Guide - Methods 中的从实例方法中修改值类型小节。

标签: swift function class


【解决方案1】:

来自The Language Guide - Methods

在实例方法中修改值类型

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

但是,如果您需要修改结构的属性或 特定方法中的枚举,您可以选择变异 该方法的行为。然后该方法可以变异(即改变) 它在方法中的属性,以及它所做的任何更改 当方法结束时被写回原始结构。这 方法还可以为其隐含的self 分配一个全新的实例 属性,并且这个新实例将在 方法结束。

您可以通过在前面放置 mutating 关键字来选择加入此行为 该方法的 func 关键字 ...

因此,我们需要包含关键字mutating 以允许 类型的成员(例如函数)改变其成员(例如成员struct 的属性)。改变值类型实例的成员意味着改变值类型实例本身(self),而改变 reference 类型实例的成员并不意味着引用类型实例的引用(即被认为是self) 发生了变异。

因此,由于 class 是 Swift 中的引用类型,我们不需要在 Zombie 类的任何实例方法中包含 mutating 关键字,即使它们改变了实例成员或类。如果我们说改变实际的类实例fredTheZombie,我们指的是改变它的实际reference(例如指向另一个Zombie 实例)。

[†]:作为另一个例子,我们可以使用例如mutating 吸气剂 (get);在这种情况下,我们需要明确地标记它,因为默认情况下它们是nonmutating。另一方面,Setter (set) 默认为 mutating,因此即使它们改变值类型的成员,也不需要 mutating 关键字。

【讨论】:

    【解决方案2】:

    mutating 与类无关,仅与值类型有关,例如structenum

    【讨论】:

      【解决方案3】:

      没有变异函数

      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()
      

      在类中,所有 func 都在发生变异。但是对于 struct 和 enum 我们需要指定。

      【讨论】:

        【解决方案4】:

        另一个易于理解的示例,已在 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)
        

        【讨论】:

          猜你喜欢
          • 2018-10-22
          • 1970-01-01
          • 2014-03-25
          • 2021-09-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-27
          相关资源
          最近更新 更多