本站已关停,现有内容仅作科研等非赢利用途使用。特此声明。
查看: 2774|回复: 0
打印 上一主题 下一主题

Dart 中的 const 与 final

[复制链接]
跳转到指定楼层
1#
发表于 2013-3-19 04:13:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hanguokai 于 2013-4-2 22:56 编辑

原文:http://han.guokai.blog.163.com/b ... 271201321911119331/

起初,我也对 const 和 final 的区别感到迷惑,并且在日常的快速开发中这两个修饰符用的不多。因此我查了一些解释,在这里做个整理记录。
概念上说,final 表示不可变,只能赋值一次,初次赋值之后就不能再赋其它值了,是只读变量。而 const 表示常量,更准确地说是编译时常量,因此 const 也是只读的、不可变的。const 和 final 都可以表示不可变,但又有细微的差异。

变量声明
var 或者类型可以声明变量,而 const 和 final 也可以用于声明变量。声明 var 的地方可以用 const 或 final 代替。声明类型的地方可以与 const 或 final 组合使用。例如下面这样声明都是可以的:
  1. var a = 1;
  2. const a = 1;
  3. final a = 1;

  4. int a = 1;
  5. const int a = 1;
  6. final int a = 1;
复制代码
这里 const 和 final 没有区别,因为变量 a 被立即赋值为一个数字常量。

区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时就初始化,并且赋值必需为编译时常量。
区别二:final 是惰性初始化,即在运行时第一次使用之前才初始化。而 const 是在编译时就确定值了。

编译时常量是指:字面量(如数字、bool、字符串、List的字面量形式)、其它常量 或者 常量的算术运算,也可以是这些的组合形式(递归要求),简单地说常量就是可以在编译时确定的值。
  1. const a = 8;
  2. const b = false;
  3. const c = a;
  4. const d = 5 * 3;
  5. const e = a * d + 2;
复制代码
而其它形式,比如一个函数调用的返回值、实例化一个新的对象就不是编译时常量了。
  1. final x = new DateTime.now();//ok
  2. const x = new DateTime.now();//error

  3. final y = sin(90);//ok
  4. const y = sin(90);//error
复制代码
final 实例成员
类中的 final 成员要么在声明时直接初始化,要么在初始化列表中初始化:
  1. class X {
  2.   final a;
  3.   X(this.a){
  4.   }
  5. }

  6. class X {
  7.   final a;
  8.   X(a): this.a = a{
  9.   }
  10. }

  11. class X {
  12.   final a = 0;
  13.   X(){
  14.   }
  15. }
复制代码
const 实例成员只能直接声明。
  1. class X {
  2.   const a = 0;
  3.   X(){
  4.   }
  5. }
复制代码
常量对象和常量构造函数
前面说的编译时常量还包括常量对象,也就是通过 const 构造函数创建的对象。
如果一个类的所有实例成员都是 final 或 const 实例成员,那么该类所创建的对象的状态就是不可变的。这种情况下就可以定义 const 构造函数,const 构造函数创建的对象就是常量对象。在语法上,const 构造函数要在构造函数前面加上 const 修饰符,同时用 const 代替 new 来调用构造函数。也可以用 new 调用 const 构造函数,但那样就不能用 const 声明该变量了。此外,const 构造函数也不能有函数体。
  1. class X {
  2.   // all instance variables are final or const
  3.   const a = 1;
  4.   final b;
  5.   const X(this.b); // no body
  6.   static const m = const X(3);//ok, a static const member
  7. }

  8. main(){
  9.   const x = const X(3);// ok
  10.   const x = new X(3);// error
  11.   final x = const X(3);// ok
  12.   final x = new X(3);// ok
  13. }
复制代码
常量对象还有一个特点,相同的常量对象始终只有一个。
  1. identical(const X(3), const X(3)) // =>true

  2. getConst() => const [1, 2];
  3. main() {
  4.   var a = getConst();
  5.   var b = getConst();
  6.   identical(a, b); // =>true
  7. }
复制代码
区别三:const 可以修饰变量,也可以修饰值(value)。而 final 只用来修饰变量。
  1. const list = [1, 2, 3]; // error
  2. const list = const [1, 2, 3]; // ok
  3. const list = const [new DateTime.now(), 2, 3]; // error, because new DateTime.now() is not const
  4. const list = const [const X(3), 2, 3]; // ok

  5. var x = 5;
  6. const list = const[x]; //error

  7. const x = 5;
  8. const list = const[x];//ok

  9. //final、var或类型定义的变量都不要求右边必需是 const,但右边的 const 修饰符要求值必需是常量
  10. final list = [1, 2, 3]; // ok
  11. final list = const [1, 2, 3]; // ok
复制代码
const 修饰值的时候,要求值必需是常量或由常量组成。var、final等在左边定义变量时,并不关心右边是不是常量。但如果右边用了 const,那么不管左边是什么要求,右边都必需是常量。
ChinaGDG.com
回复

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表