Swift 变量
变量用来保存会变化的值,Swift 用 var 声明变量。
和 C、Java 不同,Swift 的变量必须先初始化才能读取,编译器不允许使用没有赋值的变量。
本篇讲 var 的声明与修改、类型标注与类型推断、延迟初始化、命名规则和字符串插值;确定之后不再改变的值请用 let,写法见《Swift 常量》。
用 var 声明变量
var 声明一个可以重新赋值的变量,第一次赋值叫初始化,之后每次赋值都会覆盖旧值。
变量名写在 var 后面,等号右边是初始值。
实例
// var 声明变量,声明后可以重新赋值
var site = "www.runoob.com"
print(site)
site = "RUNOOB"
print(site)
// 变量的新值可以基于旧值计算
var visits = 100
visits = visits + 50
print("访问量:\(visits)")
运行结果:
www.runoob.com RUNOOB 访问量:150
同一个变量可以反复赋值,但每次赋的值必须和它当前的类型一致,否则编译不通过。
如果一行里只写一个变量名而不做别的事,编译器会给出 variable is unused 的警告,提醒你多半忘了写赋值目标。
类型标注与类型推断
声明变量时可以直接写类型,也可以交给编译器推断,两种写法都合法。
大多数情况下,编译器能根据初始值推断出准确的类型,所以类型标注可以省略。
实例
var count = 43
// 类型标注:显式写明类型
var site: String = "RUNOOB"
var price: Double = 9.9
print(count, site, price)
运行结果:
43 RUNOOB 9.9
类型标注的语法是「变量名冒号空格类型」,例如 var site: String,冒号不能写成等号。
什么时候必须显式标注?下面几种情况推断不出来,或者推断结果不符合预期。
| 场景 | 写法 | 原因 |
|---|---|---|
| 只有声明没有初始值 | var name: String | 没有值可推断 |
| 浮点需要单精度 | var ratio: Float = 0.5 | 默认推断为 Double |
| 整数需要指定位宽 | var small: Int8 = 10 | 默认推断为 Int |
| 空数组需要元素类型 | var list: [String] = [] | 空字面量无法推断 |
Swift 的数值字面量还有一套默认推断规则:带小数点的字面量默认是 Double,整数字面量默认是 Int。
实例
var names: [String] = []
names.append("Runoob")
print(names)
// 想要单精度浮点时必须标注,不标注会推断为 Double
var ratio: Float = 0.5
print(ratio)
运行结果:
["Runoob"] 0.5
一行里也可以声明多个变量,每个变量各自推断或标注类型,彼此的类型可以不同。
实例
var x = 1, y = 2, z = 3
print(x + y + z)
// 同一行也可以声明不同类型的变量,各自推断
var count = 3, ratio = 0.5, name = "RUNOOB"
print(count, ratio, name)
运行结果:
6 3 0.5 RUNOOB
唯一的要求是每个变量都能确定类型:要么有初始值,要么写了类型标注。写成 var x = 1, y 会报 type annotation missing in pattern。
变量的延迟初始化
变量不一定要在声明的那一行就赋值,可以只声明类型,稍后再赋值。
这种写法叫延迟初始化,只要在读取之前完成赋值就行,编译器会跟踪每个变量是否已经初始化。
实例
var site: String
site = "www.runoob.com"
print(site)
// 变量可以反复赋值,最后一次的值生效
var status = 0
status = 1
status = 2
print("status =", status)
运行结果:
www.runoob.com status = 2
延迟初始化最常见的场景是:值要等某个条件成立后才能算出来,或者要等到能拿到依赖的数据。
注意:延迟初始化不是 lazy。这里是在使用之前完成一次赋值,而 lazy 是属性首次访问时才计算,属于属性的一种修饰,会在《Swift 属性》介绍。
变量命名规则
Swift 的标识符规则很宽松,但宽松不等于随便写。
变量名可以由字母、数字、下划线以及大部分 Unicode 字符组成,但不能以数字开头,也不能包含空格、连字符、数学符号。
实例
var 课程名称 = "Swift 教程"
// 希腊字母标识符
var π = 3.14159
print(课程名称, π)
// 推荐的小驼峰写法
var siteName = "RUNOOB"
var isLoading = true
print(siteName, isLoading)
运行结果:
Swift 教程 3.14159 RUNOOB true
虽然中文和希腊字母都能编译,但正式项目建议统一使用英文小驼峰,方便团队协作和全局搜索。
下面这些命名习惯值得遵守。
| 规则 | 推荐 | 不推荐 |
|---|---|---|
| 见名知义,不用无意义缩写 | maxRetryCount | mrc、a1 |
| 布尔值用 is、has、can 开头 | isLoading | loading |
| 不要用下划线开头 | siteName | _siteName |
| 不要用关键字 | className | class |
如果确实要用关键字当名字,只能用反引号包裹,例如 var `class` = "Swift",但这不是好习惯。
字符串插值
字符串插值是把变量或表达式的值直接嵌进字符串里的语法,比手动拼接更清晰。
语法是在双引号内部写反斜杠加圆括号,括号里放变量或任意表达式。
实例
var site = "www.runoob.com"
var year = 2024
print("欢迎访问 \(site),\(name) 教程更新于 \(year) 年")
// 插值里可以放表达式
var a = 3, b = 4
print("\(a) + \(b) = \(a + b)")
运行结果:
欢迎访问 www.runoob.com,Runoob 教程更新于 2024 年 3 + 4 = 7
插值里的表达式不能包含未转义的双引号和反斜杠,如果要在插值里写字符串,需要嵌套转义或者改用拼接。
插值默认调用值的 description 属性,所以自定义类型也能插值,输出的是它的描述。
注意:插值符号是反斜杠加左圆括号 \(,结尾是右圆括号,不要漏写或者写成 {}。如果确实要输出一个反斜杠,写两个反斜杠 \\。
常见问题
下面是变量部分最常被问到的几个问题。
什么时候该用 var
只有值确实需要改变时才用 var,例如计数器、累加器、状态标志;其余情况优先用 let,完整的判断标准见《Swift 常量》。
类型推断错了怎么办
加上类型标注即可,例如 var ratio: Float = 0.5,不加标注时 0.5 会被推断为 Double。
能不能一行声明多个变量
可以,一行里的每个变量各自推断或标注类型,彼此类型可以不同,例如 var x = 1, y = 2.5;只要每个变量都有初始值或类型标注,就不会报错。
