我正在查看Apple的Arkit项目示例。自从我一直在学习以来,我一直试图理解代码。我看到一个将其自身设置为等于另一个功能的功能,有人可以解释一下这些功能到底在做什么。请详细介绍一下。在代码中,“ muting func normalize()”将self设置为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)
}
答案 0 :(得分:1)
Swift中的值类型可以是可变的和不可变的。因此,当您创建struct(或任何其他值类型)并将其分配给变量(var)时,它是可变的,您可以对其调用normalize()。这意味着该结构不会被复制到另一个内存中,而是会在适当位置进行更新(就像引用类型一样)。但是,当您将其分配给常量(let)时-无法对其进行更改,因此,在此结构中更新值的唯一方法是使用normalized()方法创建具有更新值的新值。关于您的问题-normalize()只是重用逻辑来标准化normalized()中的向量。因此,这是完全好的解决方案。仅在可变方法中允许分配给self。基本上是用新的重写struct的值。
答案 1 :(得分:0)
我假设此片段位于struct
中,而不是类中。
self.normalized()
制作self
的副本,并按其长度除以副本的组成部分,然后返回副本。 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()
更改了位置
修改
可汗在评论中问:
我无法理解的是为什么我们必须再次创建一个可以使用“ func normalized”的功能
要指出的是为什么我们不能做这样的事情:
var a = SCNVector3(3, 4, 0)
a = a.normalized()
完全没有normalise()
功能吗?
以上内容与a.normalize()
具有完全相同的效果,我认为[1]是更好的样式,更“实用”。
我认为a.normalize()
存在仅是因为在Swift中同时提供两种形式的函数是很常见的。例如,对于集合,您同时拥有union()
和formUnion()
:第一个返回一个集合与另一个集合的并集,第二个返回一个集合与它本身和另一个集合的并集。在某些情况下,该功能的就地版本可能更有效,但我认为不能使用此normalize
函数。
您选择使用哪种取决于您的偏好。
[1]实际上,更好的样式是
let a = SCNVector3(3, 4, 0).normalized()