如果一个变异函数设置它自己等于另一个函数,这意味着什么

What does it mean if a mutating function setting it's self equals to another function

我正在浏览 Apple 的 Arkit 项目示例。我一直在努力理解代码,因为我还在学习。我看到一个函数将其自身设置为另一个函数,有人可以解释一下这些函数到底在做什么吗?请在 detail.In 中简要说明 "mutating func normalize()" 将其自身设置为 self.normalized 的代码,这是为什么。这段代码在做什么。我们能不能简单地调用 "func normalized()" 好像我们正在重新创建相同的函数。

mutating func normalize() {

   self = self.normalized()
}


func normalized() -> SCNVector3 {

    if self.length() == 0 {
      return self
  }
    return self / self.length()
}



func length() -> CGFloat {

    return sqrt(self.x * self.x + self.y * self.y)

    }

我假设此片段位于 struct 而不是 class。

self.normalized() 复制 self 并将副本的组件除以其长度,然后 returns 复制。 self 不受影响。

self.normalize() 获取 self 的规范化版本,然后用副本替换 self。所以原地改变。

在幕后,每个成员函数都将 self 作为隐式参数传递。即对于编译器来说,声明看起来像这样:

func normalised(self: SCNVector3) -> SCNVector3

mutating 放在函数定义的前面会使隐藏参数 inout

func normalise(self: inout SCNVector3)

所以,如果你有

var a = SCNVector3(3, 4, 0)
let b = SCNVector3(4, 3, 0)
let c = b.normalized() 
a.normalize()

在该代码之后,c 将是 (0.8, 0.6, 0),而 a 将是 (0.6, 0.8, 0)b 将保持不变。

请注意,a 必须用 var 声明,因为它已被 normalise()

原地更改

编辑

汗在评论中提问:

What i am not able to understand is why do we have to create a func again we can use "func normalized"

重点是为什么我们不能做这样的事情:

    var a = SCNVector3(3, 4, 0)
    a = a.normalized()

根本没有normalise()功能?

以上将与 a.normalize() 产生完全相同的效果,在我看来[1],是更好的风格,更 "functional"。

我认为 a.normalize() 存在只是因为它在 Swift 中很常见,以提供两种形式的功能。例如,对于集合,你有 union()formUnion():第一个 returns 一个集合与另一个集合的并集,第二个用它自己和另一个集合的并集替换一个集合。在某些情况下,函数的就地版本可能更有效,但我认为,使用此 normalize 函数并非如此。

您选择使用哪种是您的喜好。


[1]其实更好的风格是

let a = SCNVector3(3, 4, 0).normalized()

Swift 中的值类型可以是可变的和不可变的。因此,当您创建 struct( 或任何其他值类型) 并将其分配给变量 (var) 时,它是可变的,您可以在其上调用 normalize() 。这意味着 struct 不会被复制到另一个内存中,并且会在适当的位置更新(就像引用类型一样)。但是当你将它分配给常量 (let) 时——它不能被改变,所以更新这个结构中的值的唯一方法是像 normalized() 方法一样创建一个具有更新值的新值。关于你的问题——normalize() 只是重用逻辑来规范化 normalized() 中的向量。所以这是完全好的解决方案。分配给 self 只允许在可变方法中使用。它基本上是用新的重写结构的值。