变量与基本类型

本节讲解 Dart 的变量与基本数据类型。

注意:示例代码使用了dart核心库的print函数来打印信息,后续章节将不再进行说明

变量

变量用于存储数据,Dart 中”万物皆对象”,即变量存储的都是对象的引用,或者说它们都指向某个对象。

变量声明

有两种基本的变量声明方式,一是不指定类型,即使用var

  1. // name变量存储一个内容为'bob'的字符串对象
  2. var name = 'bob';

另一种是指定类型

  1. // 显式指明类型,效果与第一种方式一样
  2. String name = 'bob';

因为有类型推导,以上两种声明方式的效果实际是一样的。官方推荐在函数内的本地变量尽量使用var声明。

在变量类型并不明确的场景下,可以使用dynamic关键字,如下:

  1. // dynamic变量可以进行任意类型的赋值以及变量和方法的访问
  2. dynamic cache = 'bob';
  3. cache = 123;
  4. cache = new SomeClass();
  5. cache.method();
  6. print(cache.name);

注意:dynamic变量不会进行类型检查,它的类型安全完全由开发者自己负责!

默认值

显著区别于其他语言,无论什么类型的变量,在没有赋初始值的情况下,默认值为null

  1. // 未指定类型的变量
  2. var name;
  3. // 指定为数字类型的变量
  4. int age;
  5. // 使用print函数打印,两个变量都为null
  6. print(name); // null
  7. print(age); // null

null也是对象,所以也可以理解为:未初始化的 Dart 变量都指向null对象。

作用域

Dart 使用词法作用域(也称为静态作用域),即变量的作用域在定义时确定。

作用域范围由变量所处代码块(大括号)的层级决定,层级越深,作用域越小,层级越浅,作用域越大。

不被任何代码块包含的变量通常称为顶层变量,它们的作用域最大

  1. var top = 'top'; // 顶层变量,作用域最大
  2. main() {
  3. var inMain = 'main';
  4. print(top); // top
  5. print(inMain); // main
  6. print(inFn); // 错误,无法访问
  7. print(inIf); // 错误,无法访问
  8. fn() {
  9. var inFn = 'fn';
  10. print(top); // top
  11. print(inMain); // main
  12. print(inFn); // fn
  13. print(inIf); // 错误,无法访问
  14. if (top) {
  15. var inIf = 'if'; // 最内层的变量,作用域最小
  16. print(top); // top
  17. print(inMain); // main
  18. print(inFn); // fn
  19. print(inIf); // if
  20. }
  21. }
  22. }

final 与 const

如果变量内容不会改变,建议使用finalconst替代var,或者搭配类型使用。

final表示变量只能被赋值一次;const表示变量是编译时常量,const变量默认为final变量。

需要注意的是,顶层final变量与类变量在首次访问时才执行初始化

  1. // 定义final变量并使用函数进行初始化
  2. final name = getName();
  3. // name = 'john'; // 错误,final变量不能再次赋值!
  4. // 定义获取name的函数(下一节将对函数进行讲解)
  5. String getName() {
  6. print('getName');
  7. return 'bob';
  8. }
  9. // 常量
  10. const pi = 3.14;
  11. // 由常量值计算得到的也是常量
  12. const area = pi * 2 * 2;
  13. main() {
  14. print(pi); // 3.14
  15. print(area); // 12.56
  16. print(name); // 先打印 getName,再打印 bob,即直到name变量被访问时getName函数才执行
  17. }

基本数据类型

Dart 有三种基本数据类型:数字、字符串与布尔。基本数据类型一般通过字面量进行创建,如:1,’bob’,true 等。

数字

数字类型有两种,一种是整数int,另一种是双精度浮点数double

intdouble都继承自数字类型num,在需要同时支持整数与浮点数时可以使用num

  1. int age = 28;
  2. double percent = 0.23;
  3. num price = 2.3;

数字对象具备多种数学计算相关的属性与方法

  1. int size = 9;
  2. // 是否偶数
  3. print(size.isEven); // false
  4. // 是否奇数
  5. print(size.isOdd); // true
  6. // 转换为6进制字符串
  7. print(size.toRadixString(6)); // 13
  8. ......
  9. double pi = 3.1415926;
  10. // 向上取整
  11. print(pi.ceil()); // 4
  12. // 转成整形
  13. print(pi.toInt()); // 3
  14. // 转换为固定精度字符串
  15. print(pi.toStringAsPrecision(2)); // 3.1
  16. ......

字符串

字符串是由单引号或双引号包裹的字符序列,它支持使用${ 表达式 }进行插值,当表达式为变量时可以省略{}

  1. String name = 'bob';
  2. String message = 'Hi ${name.toUpperCase()}'; // Hi BOB
  3. String text = 'Welcome $name'; // Welcome bob

连接多个字符串可以使用+,而多个相邻的字符串也会自动连接在一起,多行字符串则使用'''"""创建

  1. // 连接字符串
  2. String message1 = 'Hello' + ' World'; // Hello World
  3. // 相邻字符串会自动连接
  4. String message2 = 'Hello'
  5. ' World'; // Hello World
  6. // 使用'''创建多行字符串
  7. String multiMessage = '''
  8. Hello
  9. again!
  10. '''; // Hello
  11. // again!

字符串对象自带多种实用属性与方法

  1. String name = 'bob';
  2. // 长度
  3. print(name.length); // 3
  4. // 是否为空
  5. print(name.isEmpty); // false
  6. // 子字符串
  7. print(name.substring(1)); // ob
  8. // 是否以某字符开头
  9. print(name.startsWith('b')); // true
  10. // 替换所有
  11. print(name.replaceAll('b', 'w')); // wow
  12. ......

布尔

布尔类型只包含两个对象,truefalse

有别于很多动态语言,Dart 中的true是唯一“正确”的值,所有非true的值都被视为false

  1. // 以下Dart代码也是合法的JavaScript代码,但执行结果完全不同
  2. var name = 'bob';
  3. if (name) {
  4. // 在JavaScript中,name被视为true,此处代码会执行
  5. // 在Dart中,name被视为false,此处代码不会执行
  6. var message = 'Hi ' + name;
  7. ......
  8. }