在使用变量存储数据时,首先需要 声明 变量(也被称为 定义 变量)。变量声明的主要作用是通知系统提前为变量分配好内存空间,以便后续使用。
对代码清单1-1进行修改,在程序中声明一个变量。修改后的代码如代码清单2-1所示。
01 main() {
02 var info: String = "你好,仓颉!"
03 println(info) // 输出变量info并换行
04 }
在以上示例中,我们使用以下代码声明了一个String类型的可变变量info,其初始值为"你好,仓颉!":
var info: String = "你好,仓颉!"
编译并执行该程序,输出结果和代码清单1-1的输出结果是完全一样的。
在执行示例程序时,系统自动会从main开始,自上往下逐行执行花括号中的代码。首先是第2行代码,通过这个变量声明,系统为我们准备好了一个名为info、值为"你好,仓颉!"的String类型的可变变量。接着是第3行代码,使用println函数输出了变量info的值。在第3行代码中,通过 变量名 info访问了变量的值。
声明变量的语法格式如下:
let|var 变量名[: 数据类型] [= 初始值]
这是本书中出现的第1个语法说明,本书后续出现的所有语法说明都遵循以下约定:
● 粗体字部分表示关键字,它的写法是固定不变的,如关键字“let”“var”;非粗体字部分表示需要根据需求填写,如“变量名”“数据类型”等。
● 符号“|”表示多个并列的关键字,只能取其中一个,如关键字“let”和“var”只能二选一。
● 由一对方括号“[]”括起来的部分表示是可选的,即该部分不是必须填写的,如“[: 数据类型]”和“[= 初始值]”。
为了提高程序代码的可读性,建议在某些符号(如“:”“,”)后面加上一个空格,在某些操作符(如“=”“+”)的前后各加上一个空格。多多观察示例程序,可以帮助你很快了解这些编程规范。
仓颉使用关键字let或var来声明变量,其中,let声明的是 不可变变量 ,var声明的是 可变变量 (两者的区别详见2.2节)。
在关键字之后,就是自定义的变量名。变量名是一种标识符。在程序中,可以通过变量名来访问变量。
仓颉程序中的变量名、函数名、类型名等,都属于 标识符 。标识符命名必须遵循以下命名规则。
● 一个合法的标识符名称可以有两种开头:一种是以一个英文字母开头,另一种是以任意数量连续的下画线(_)加上一个英文字母作为开头。标识符名称的开头后可以是任意长度的英文字母、数字或下画线。
● 不可以使用关键字作为标识符。
● 区分大小写,如info和Info是两个不同的标识符。
符合命名规则的标识符名称,被称为合法标识符;不符合命名规则的标识符名称,被称为非法标识符。如果程序中包含非法标识符,将会导致编译错误。
以下是一些合法标识符的示例:
x // 以英文字母开头
gate9 // 以英文字母开头,之后是英文字母和数字
gate_9 // 以英文字母开头,之后是英文字母、数字和下画线
gate9_ // 以英文字母开头,之后是英文字母、数字和下画线
x1_y1_z1 // 以英文字母开头,之后是英文字母、数字和下画线
_x // 以一个下画线和英文字母开头
_x1_y1_z1 // 以一个下画线和英文字母开头,之后是数字、下画线和英文字母等
__x // 以两个下画线和英文字母开头
以下是一些非法标识符的示例:
9gate // 以数字开头
class // class是关键字
除了必须遵循的命名规则,我们还建议在给标识符命名时使用一个或多个有意义的单词组合,做到“见名知意”。
变量的命名也需要遵循以上规则。另外,对于一般的变量,推荐使用 小驼峰命名风格 来命名,即如果变量名由多个单词构成,那么第一个单词的首字符小写,后面每个单词的首字符大写,其余字符都小写,中间不使用下画线。举例如下:
teacherName // 教师姓名
ageOfStudent // 学生年龄
totalScore // 总分
isScorePassed // 分数是否通过
数据类型表示变量存储的是何种类型的数据。在声明变量时要确定变量的数据类型,并且变量的数据类型在声明之后不可以被更改。仓颉本身内置了多种数据类型,并且也支持自定义数据类型。下面介绍4种常用的基本数据类型,先声明以下4个变量:
main() {
let teacherName: String = "刘玥"
var ageOfStudent: Int64 = 19
var totalScore: Float64
var isScorePassed: Bool
}
接下来,让我们来逐行解释一下。
let teacherName: String = "刘玥"
以上代码声明了一个String类型的变量teacherName。String类型(也被称为字符串类型)在前面的示例中已经出现过,用于存储文本内容。显然,教师的姓名属于文本内容,所以将该变量声明为String类型。
var ageOfStudent: Int64 = 19
以上代码声明了一个Int64类型的变量ageOfStudent。Int64类型是众多整数类型中最常用的一种,用于存储整数。除非是一些特殊的场景,在一般情况下,学生的年龄应该是整数,所以可以将其声明为整数类型。
var totalScore: Float64
以上代码声明了一个Float64类型的变量totalScore。Float64类型是一种常用的浮点类型,用于存储具有小数部分的实数。这里我们将表示总分的变量totalScore定义为浮点类型,即认为总分是可以带小数的。当然,如果在程序设定中总分是整数,那么也可以将变量totalScore定义为整数类型。
var isScorePassed: Bool
最后这行代码声明了一个Bool类型(布尔类型)的变量isScorePassed。布尔类型用于表示逻辑中的 真 和 假 ,只有两个字面量:true和false。布尔类型在程序中常用于表示两种互斥的状态。例如,isScorePassed用于表示分数通过(true)和分数不通过(false)这两种互斥的状态。
仓颉要求每个变量 在使用前 必须完成 初始化 ,否则会引发编译错误。例如,在以下示例代码中,在声明变量totalScore时没有指定初始值,并且之后也没有对totalScore进行初始化,就直接使用println访问了totalScore,导致编译错误。
main() {
var totalScore: Float64
println(totalScore) // 编译错误:变量totalScore在使用时没有初始化
}
如果要避免上述错误,可以在声明时给totalScore指定初始值,或者在声明之后使用赋值表达式对totalScore进行初始化。例如,可以将以上代码修改为:
main() {
var totalScore: Float64 = 0.0 // 在声明时对变量进行初始化
println(totalScore)
}
在一般情况下,仓颉要求在声明变量时就对变量进行初始化,仅在一些特定的情况下才可以在声明变量时 缺省 (省略不写)初始值。例如,对于局部变量,如上述代码中的totalScore,仓颉允许在定义时不对该变量进行初始化(此时 必须 指明数据类型),但是在变量第一次被读取之前,必须完成初始化工作。可以使用如下的赋值表达式对变量进行初始化:
变量名 = 初始值
其中,“=”是赋值操作符,其作用是将“=”右边的初始值赋给左边的变量。
针对上面的示例,如果在声明之后对totalScore进行初始化,可以将代码修改为:
main() {
var totalScore: Float64
totalScore = 0.0 // 使用赋值表达式对变量进行初始化
println(totalScore)
}
局部变量的概念将在6.3节进行详细介绍。目前,读者只需要知道在main中定义的变量都属于局部变量即可。
在一个商场管理软件中,有以下4种数据需要存储,请读者分别为它们定义对应的变量,注意选择合适的数据类型,以及简短的、具有描述性的变量名。
● 停车场的停车位编号。假定该商场的停车场总共只有一层一个分区,停车位编号范围为1~1000号。当前车位编号为668号。
● 儿童用品区的一双童鞋的价格为99.8元。
● 某商铺在商场中的地址编号为1-16A。
● 商场中央空调的当前开关状态为“关”。
在声明变量时,当初始值的类型明确的时候,编译器可以根据初始值自动推断出变量的数据类型,此时,可以缺省数据类型。
以下两行代码是完全等效的:
let teacherName: String = "刘玥"
let teacherName = "刘玥"
在以上变量声明中,初始值为字符串类型的字面量"刘玥",因此如果缺省数据类型,编译器会将teacherName推断为String类型。
在没有数据类型上下文可参考的情况下,整数类型的字面量会被推断为Int64类型,浮点类型的字面量会被推断为Float64类型。
var ageOfStudent = 19 // 19被推断为Int64类型,因此ageOfStudent也被推断为Int64类型
var totalScore = 0.0 // 0.0被推断为Float64类型,因此totalScore也被推断为Float64类型
在以上两个变量声明中,缺省了数据类型,因此编译器会根据初始值的类型来推断变量的类型。整数类型的字面量19为Int64类型,因此ageOfStudent被推断为Int64类型;浮点类型的字面量0.0为Float64类型,因此totalScore被推断为Float64类型。
修改2.1.2节的练习中的4个变量声明,尝试在声明变量时缺省数据类型。