变量和函数
变量¶
用 var
声明可更改的变量,let
声明不可更改的变量(常量)。
声明变量时,在变量名后用 : Type
声明类型:
1 2 3 |
|
如果上下文明确,编译器能够自动确定变量的类型,那么类型声明可以省略(比如,42
是整数字面值,自动推断为 Int
类型):
1 2 3 |
|
需要注意的是,Swift 不允许隐式类型转换,进行类型转换只能通过目标类型的构造函数进行:
1 2 3 4 5 |
|
var
和 let
声明的变量在使用之前必须初始化,否则编译不通过。不同之处在于,var
可以多次赋值,而 let
只能赋值一次。
Swift 支持空值(Optional),表示变量的值“不存在”。在类型后加上 ?
声明可空的变量,关键字 nil
表示值为空:
1 2 3 4 5 |
|
注意到,即使 Optional 值不为空,Optional 与原来的类型是不同的两个类型,不能直接获取其值。
Optional 的值有两种读取方法。第一种是当确保 Optional 不为空时,在变量名后加上 !
表示强制解除包装获取值。当值为空时,使用 !
会导致运行错误,程序直接崩溃:
1 2 3 4 5 6 7 |
|
另一种是建议使用的方法,通过 Swift 的一个语法糖 if let
(或 if var
)实现:
1 2 3 4 |
|
相当于
1 2 3 4 |
|
如果 if let
大括号内不需要再引用原来的 Optional,一般 if let
语句 let
后面新的变量名直接使用原有的变量名,省去重复命名的困扰:
1 2 3 4 |
|
另外,可以使用 ??
给 Optional 提供默认值,当值为空时,使用默认值:
1 |
|
与 Optional 有关的更多条件判断语句将在后面介绍。
函数¶
使用关键字 func
声明函数。函数参数的声明与变量声明类似,需要显式指出类型;返回值用 -> Type
显式指出;可以为参数指定默认值:
1 2 3 |
|
如果函数体只有一行,可以省略 return
:
1 2 3 |
|
调用时,需要写出标签:
1 |
|
Swift 函数声明的特点是,其参数有两个“名称”:参数名(函数体内部使用)和标签(调用时指出),按照 标签 参数名: 类型
的形式声明。如果不区分标签和函数名,则使用 参数名: 类型
声明。
对于上面的 add
,参数只有名称,a
和 b
既作为参数名称,又作为标签。与之对应,有时候我们将标签和参数名分离,如 Array
的 remove
方法:
1 2 |
|
调用函数时,必须写出标签,因此上面的调用不能写成 add(1, 1)
。如果需要省略标签,在标签的位置使用下划线 _
替代:
1 2 |
|
Note
Swift 的标签和参数名的设计有以下几点好处:
1. 需要明确写出标签,使得调用时语义更加明确。
C 风格函数调用时没有标签,各参数的顺序可能会造成困扰,比如 memcpy(buf1, buf2)
,究竟哪个是 src
,哪个是 dest
?
而 Swift 中可以利用标签来明确:
1 |
|
2. 标签增强代码可读性,同时参数名保持应有的含义
还是上面的例子。我们可以将 copyMemory
的标签和参数名分离:
1 2 3 4 5 6 |
|
这样调整之后,函数调用 copyMemory(from: buffer1, to: buffer2)
就可以用英文从左往右读出来:“Copy memory from buffer 1 to buffer 2”。这是 Swift 的 三个特点 之一:expressive。
同时,函数体内部引用两个参数时仍然保持 source
和 dest
的语义,避免了 print("Copying from \(from) to \(to)")
这样的情形。
关于标签和参数名的使用规范,详见 Swift 的 API Design Guidelines。