Dart的变量与类型
在Dart中,我们可以用var或者具体的类型来声明一个变量。当使用var定义变量时,表示类型是由编译器推断决定的,当然你也可以用静态类型去定义变量,更清楚地跟编译器表达你的意愿,这样编辑器和编译器就能使用这些静态类型,向你提供代码补全或者编译警告的提示了。
在默认情况下,未初始化的变量的值都是null。如下代码:
int a;
print(a);
String str;
print(str);
其打印结果都是null。
Dart是类型安全的语言,并且所有类型都是对象类型,都继承自顶层类型Object,因此一切变量的值都是类的实例(即对象),甚至数字、布尔、函数和null也都是继承自Object的对象。
Dart的数值类型是num,只有两种子类:int和double。前者代表整数类型,后者则是浮点数的抽象。
为了表示布尔值,Dart使用了一种名为bool的类型。在Dart里,只有两个对象具有bool类型:true和fault,它们都是编译时常量。
Dart是类型安全的,因此我们不能够使用if(nonbooleanValue)之类的在Objective-C中可以正常工作的代码,而应该显示地检查值。
如下所示,检查变量是否为0,在Dart中需要显示地直接与0去比较:
// 检查是否为 0.
var number = 0;
if(number == 0){
};
Dart中的String是由UTF-16的字符串组成。构建字符串字面量时既能使用双引号,也能使用单引号,还能在字符串中嵌入变量或者表达式:你可以使用${express}把一个表达式的值放进字符串。而如果是一个标识符,你可以省略{}。
下面这段代码就是内嵌表达式的例子。我们把单词'cat'转成大写放入到变量s1的声明中:
var s = 'cat';
var s1 = 'this is a uppercased string: ${s.toUpperCase()}';
为了获得内嵌对象的字符串,Dart会调用对象的toString()方法。而常见字符串的拼接,Dart则通过内置运算符“+”实现。比如,下面这条语句会如你所愿声明一个值为“Hello World!”的字符串:
var s2 = 'Hello' + ' ' + 'World!' ;
对于多行字符串的构建,你可以通过三个单引号或者三个双引号的方式声明,这与Python是一致的:
var s3 = """This is a
multi-line string.""";
List 与 Map
其他编程语言中常见的数组和字典类型,在Dart中的对应实现是List和Map,统称为集合类型。
接下来,我们一起看一段代码示例:
var arr1 = ["Tom", "Andy", "Jack"];
var arr2 = List.of([1, 2, 3]);
arr2.add(499);
arr2.forEach((value) => print(value));
var map1 = {"name":"Tom", "sex":"male"};
var map2 = new Map();
map2["name"] = "Tom";
map2["sex"] = "male";
map2.forEach((key, value) => print('$key:$value'));
这段代码分两部分:
容器中的元素也需要有类型,比如上述代码中arr2的类型是List<int>,map2的类型则为Map<String, String>。Dart会自动根据上下文进行类型判断,所以你后续往容器内添加的元素也必须遵照这一类型。
如果编译器自动推断的类型不符合预期,我们当然可以在声明时显示地把类型标记出来,这样不仅可以让代码提示更友好一些,更重要的是可以让静态分析器帮忙检查字面量中的错误,解决类型不匹配带来的安全隐患或者是Bug。
以上述代码为例,如果往arr2集合中添加一个浮点数:
arr2.add(2.2);
尽管语义上是合法的,但是编译器会提示类型不匹配,从而导致编译失败:
The argument type 'double' can't be assigned to the parameter type 'int'.
在初始化集合实例对象时,你可以为它的类型添加约束,也可以用于后续判断集合类型。
下面的这段代码,在增加了类型约束后,语义是不是更清晰了呢?
var arr1 = <String>["Tom", "Andy", "Jack"];
var arr2 = List<int>.of([1, 2, 3]);
arr2.add(499);
arr2.forEach((value) => print(value));
var map1 = <String, String>{"name":"Tom", "sex":"male"};
var map2 = new Map<String, String>();
map2["name"] = "Tom";
map2["sex"] = "male";
map2.forEach((key, value) => print('$key:$value'));
以上。