今天,在看 Then 源码时,发现了一处比较值得研究的地方
public func with(_ block: (inout Self) -> Void) -> Self {
var copy = self
block(©)
return copy
}
这部分代码是在针对 Any
类型的协议扩展里实现的。这里 with
的语义是拷贝值类型并修改(代码中针对的是 Any
,这里用值类型来说明问题)。可以看看官方的示例:
let newFrame = oldFrame.with {
$0.size.width = 200
$0.size.height = 100
}
newFrame.width // 200
newFrame.height // 100
注意,这里使用的是 inout
关键字,而且已经把它的位置放在了类型之前,这是 Swift3 的新变化 Adjusting inout Declarations for Type Decoration。
在函数调用时,如果传递的参数是引用类型,那么我们在函数中对参数的修改会直接影响到传进来的变量,这就是函数的副作用。
然而,如果传递的参数是值类型的话,我们在函数中对参数是不可以进行修改的,因为传参时函数会创建一个不变量来存储值,我们不可以对这个不变量进行修改。在 Swift2 中有个关键字 var
可以让函数创建一个变量来存储值,这样我们就可以在函数中对这个变量进行修改了。不过在 Swift3 中已经去掉了这个关键字 Removing var from Function Parameters。
如果想让值类型具备引用类型的语义,这时 inout
关键字就出场了。这个有点类似 C 语言中传递指针,我们在调用时需要加上 &
标识。这样,我们就可以愉快的对值类型进行修改了。不过,为了避免函数副作用,我们最后不要这样做。
网友评论