在声明一个Swift的方法的时候,我们一般不去指定参数前面的修饰符,而是直接声明参数:
这个方法接受一个Int的输入,然后通过将这个输入加1,返回一个新的比输入大1的Int,这其实就是一个简单的 +1器 。
有些同学在大学的C程序设计里可能学过像++这样的“自增”运算符,再加上做了不少关于“判断一个数被各种前置++和后置++折磨后的输出是什么”的考试题,所以之后写代码时也会不自觉地喜欢带上这种风格。于是同样的功能可能会写出类似这样的方法:
这是错误代码
结果发现编译错误。为什么在Swift里这样都不行呢?答案是因为Swift其实是一门“讨厌”变化的语言。所有可能的地方,都被默认为不可变的,也就是用let进行声明的。这样不仅可以确保安全,也能在编译器的性能优化上更有作为。在方法的参数上也是如此,我们不写修饰符的话,默认情况下所有参数都是let的,上面的代码等效为:
let的参数不能重新赋值,这是理所当然的。要让这个方法正确编译,我们需要做的改动是将let改为var:
现在我们的 +1器 又可以正确工作了:
正如上面的例子,我们将参数写作var后,通过调用返回的值是正确的,而luckyNumber还是保持了原来的值。这说明var只是在方法内部起作用,而不会直接影响输入的值。有些时候我们会希望在方法内部 直接 修改输入的值,这时候我们可以使用inout来对参数进行修饰:
因为在函数内部就更改了值,所以也不需要返回了。调用也要改变为相应的形式,在前面加上&符号:
最后,要注意的是参数的修饰是具有传递限制的,就是说对于跨越层级的调用,我们需要保证同一参数的修饰是统一的。举个例子,比如我们想扩展一下上面的方法,实现一个可以累加任意数字的 +N器 ,可以写成这样:
外层的makeIncrementor的返回里也需要在参数的类型前面明确指出修饰词,以符合内部的定义,否则将无法编译通过。