Dart重要概念和变量

700 阅读5分钟

重要概念

  1. 所有变量中的值都是一个_object_,每个_object_都是类的实例,甚至数字和函数、null也是_object__,所有的__object集成自__Object__类。_
  2. 尽管Dart是强类型语言,但是类型声明是可选的,因为Dart可以推断类型。如果要明确说明不指定任何类型,请使用特殊类型dynamic。
  3. Dart支持泛型类型,如List (整数列表)或List (任何类型的对象列表)。
  4. Dart支持顶级函数(例如main()),以及绑定到类或_object_的函数(也就是是静态和实例方法)。你还可以在函数内创建函数(嵌套函数或本地函数)。
  5. Dart支持顶级变量,以及绑定到类或对象的变量(静态变量或实例变量)。实例变量有时称为字段或属性。
  6. 与Java不同,Dart没有关键字public,protected和private。如果标识符以下划线(_)开头,则它对其库是私有的。
  7. 标识符可以以字母或下划线(_)开头,后跟这些字符加数字的任意组合。
  8. Dart有表达式(具有运行时值)和语句(不具有)。例如,条件表达式condition?expr1:expr2的值为expr1expr2。而if-else语句没有任何值。语句通常包含一个或多个表达式,但表达式不能直接包含语句。
  9. Dart工具可以报告两种问题:警告和错误。警告只是表明代码可能无法正常工作,但它们不会阻止程序执行。错误可能是编译时错误或运行时错误。编译时错误会阻止代码执行,运行时错误会导致代码执行时抛出exception

关键字

这些词在dart中有特殊意义,在使用时要特别注意。

深度截图_选择区域_20190725092722.png

尽量避免使用这些关键字作为标识符。如果你非要这么做,那么带有上标的词可以在某些情况下使用:

  1. 带有上标1的是上下文关键字,仅在特定位置具有含义。它们是可以在任何地方作为标识符。
  2. 带有上标2的单词是内置标识符。为了简化将JavaScript代码移植到Dart的任务,这些关键字在大多数地方都是有效的标识符,但它们不能用作类或类型名称,也不能用作导入模块时的前缀
  3. 带有上标3的单词是与Dart 1.0发布后添加的异步支持相关的关键字。不能在标记为async,async *或sync *的任何函数体中使用await或yield作为标识符。

变量

声明变量

最简单的声明

var name = 'jane';

前面我们提到了所有的值都是_object_,所以这里的变量声明其实指的是一个叫name的变量保存了一个_String object_的引用,它的值是jane
这种声明方式,Dart可以推断出name是String,但是你可以随意改变name的类型,如果一个变量不需要制定严格的类型,那么可以使用_object_或者_dynamic__:_

dynamic name = 'Bob';

_object_和_dynamic_都可以指定变量类型不限制,但是Dart推荐在使用时用_object_表示允许所有类型,而_dynamic_表示允许多个但不是全部:

void log(Object object) {
  print(object.toString());
}

/// Returns a Boolean representation for [arg], which must
/// be a String or bool.
bool convertToBool(dynamic arg) {
  if (arg is bool) return arg;
  if (arg is String) return arg == 'true';
  throw ArgumentError('Cannot convert $arg to a bool.');
}

具体参考:高效dart
还有一种变量声明是直接声明变量的类型,这个时候变量的类型将无法修改:

String name = 'Bob';

默认值

所有变量在声明的同时都可以赋值,如果只是声明变量而不赋值,那么它将有默认值_null_:

int lineCount;
assert(lineCount == null);

尽管这里已经声明了变量类型是_int,_但是别忘了,所有的值在dart中都是_object,那么给一个_object_初始值为_null,很合理。

final和const

如果你不想改变一个变量的值,那么使用_final_和_const_关键字,并且可以加上类型声明。final_表示运行时(run-time)常量,只能被设置一次值;const表示编译时(compile-time)常量,const_是隐式的_final。_

final name = 'army'; // 直接使用final;
final String nickname = 'zz'; // 加上类型声明

name = 'fool' // 报错 Error: a final variable can only be set once.

**补充说明:**实例变量只能使用_final_不能使用_const_,final_实例变量会在构造函数执行前执行。这个不难理解,定义的类在编译时就已经确定,但是这个类的实例要在类实例化时,也就是运行时才能生成,所以实例变量不能使用_const_,反过来说对于类的静态变量,应该使用_const(虽然可以使用_final,因为前面说了_const_是隐式的_final)__。
当你要声明一个编译时常量时,比如一个_number_、string、常量或者一系列常量数值的运算结果时,可以使用_const_关键字:

const bar = 1000000; // 常量数值
const double atm = 1.01325 * bar; 常量数值的运算结果

关键字不仅可以声明编译时常量,还可以用来创建常量值、构造常量的构造函数(比如List等)。所有的变量都可以具有常量值:

var foo = const []; // 右边的List是一个编译时常量
final bar = const []; // 右边的List是一个编译时常量,并且在运行时把它的引用赋给了运行时常量bar。
const baz = []; // 等价于 const baz = const [] 当在声明变量时使用了const,那么右边的值不需要在使用const

tips:const连用解释
对于上面的foo变量,我们完全可以修改它,因为它只是保存了一个编译时常量List的引用,我们修改它,只是把它指向另一个值,并没有改变这个常量List:

foo = [1, 2, 3];

但是我们不能改变baz,因为他是一个常量变量:

baz = [42]; // Error: Constant variables can't be assigned a value.