任何语言的核心都必然会描述这门语言最基本的工作原理。而描述的内容通常都要设计这门语言的语法、操作符、数据类型、内置功能等用于构建复杂解决方案的基本概念。
我分了几篇文章将对 Dart 的基本概念进行全面的总结:
下面开始正文。
在 Dart 中声明一个变量可以用 var
、final
、const
来声明,在 Dart 中文手册 中的相关描述很模糊,所以我整理之后在本文记录一下这 3 个关键字的区别。
var
用法示例:
main() {
var name = 'Bob';
name = 'leo';
print(name);
}
// output: leo
上面的代码中,名为 name
的变量引用了 一个内容为 Bob
的 String
对象,接着更改 name
的值为 leo
,最后输出 leo
。
很明显,var
的用法在 JavaScript 里是一样的,但是有一点是需要注意的,Dart 中的 var
在声明后立即赋值,之后就无法修改数据类型,例如下面的代码将会报错:
main() {
var foo = 'test';
foo = 123;
}
// Error: A value of type 'int' can't be assigned to a variable of type 'String'.
// Try changing the type of the left hand side, or casting the right hand side to 'String'.
// foo = 123;
// ^
如果只是单纯地声明一个变量,不进行赋值,则这个变量是 dynamic
类型的变量,可以任意修改数据类型:
main() {
var foo;
foo = 'test';
foo = 123;
}
下面这种使用 dynamic
关键字的写法和上面使用 var
关键字的写法是等价的:
main() {
dynamic foo = 'test';
foo = 123;
}
final 和 const
使用 final
或者 const
声明的变量只能赋值一次,赋值之后就不能再更改了,这和 JavaScript 中 const
的用法也是一摸一样,例如以下代码将会报错:
main() {
const a = 'Bob';
a = 'Leo';
}
// Error: Setter not found: 'a'.
// a = 'Leo';
// ^
// Error: Compilation failed.
final
和 const
有什么区别呢?官网是这样介绍的:
一个 final 变量只能赋值一次;一个 const 变量是编译时常量。 (Const 变量同时也是 final 变量。) 顶级的 final 变量或者类中的 final 变量在 第一次使用的时候初始化。
👴真的人晕了。。。
以我的理解就是:const
比 final
更加严格,具体有如下几种表现:
const 声明的变量,值必须是确定的
例如用 const
声明变量 foo
,赋值为 DateTime.now()
,将会报错:
main() {
const foo = DateTime.now();
}
// Error: Cannot invoke a non-'const' constructor where a const expression is expected.
// const foo = DateTime.now();
// ^^^
// Error: Compilation failed.
而用 final
声明变量 foo
,赋值为 DateTime.now()
,则会正常输出当前时间:
main() {
final foo = DateTime.now();
print(foo);
}
// output: 2019-07-03 12:21:31.350
const 声明的变量,值如果包含变量,那这些被包含的变量也必须使用 const 声明
例如声明变量 sum
,值为 foo
与 bar
之积,将正常输出 6
:
main() {
const foo = 2;
const bar = 3;
const sum = foo * bar;
print(sum);
}
// output: 6
如果你使用 final
声明上面代码中的 foo
或 bar
,将会报错:
main() {
final foo = 2;
const bar = 3;
const sum = foo * bar;
print(sum);
}
// Error: Not a constant expression.
// const sum = foo * bar;
// ^^^
// Error: Compilation failed.
如果使用 final
或者 var
声明变量 sum
,就能正常运行:
main() {
final foo = 2;
const bar = 3;
final sum = foo * bar;
print(sum);
}
// output: 6
final 声明 lists 或 maps 类型的变量,可以更改其属性,而 const 不能
Dart
中的 final
与 JavaScript
中的 const
特性非常相似,例如如下代码将正常运行:
main() {
final foo = [1, 2, 3];
foo[1] = 666;
print(foo);
}
// output: [1, 666, 3]
main() {
final foo = {'name': 'Bob'};
foo['name'] = 'Leo';
print(foo);
}
// output: {name: Leo}
而 const
就非常严格,如果你将上面代码中的 final
替换为 const
,将会报错:
main() {
const foo = [1, 2, 3];
foo[1] = 666;
print(foo);
}
// Uncaught exception:
// Unsupported operation: indexed set
main() {
const foo = [1, 2, 3];
foo[1] = 666;
print(foo);
}
// Uncaught exception:
// Unsupported operation: Cannot modify unmodifiable Map
变量的值相同时,final 将在内存中重复创建,而 const 将引用相同值
例如如下代码声明 foo
和 bar
的值都为 [1, 2, 3]
,比较 foo
与 bar
,输出 false
:
main() {
final foo = [1, 2, 3];
final bar = [1, 2, 3];
print(foo == bar);
}
// output: false
如果将上面代码中的 final
替换为 const
,则会输出 true
, 因为 const
引用的是同一份地址:
main() {
const foo = [1, 2, 3];
const bar = [1, 2, 3];
print(foo == bar);
}
// output: true
