在dart中将“ const”值分配给“ final”变量的目的是什么?

时间:2018-07-16 06:39:18

标签: dart flutter

所以我正在为Flutter做first example, 步骤4:创建无限滚动ListView

我遇到了这段代码:

class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];

  final _biggerFont = const TextStyle(fontSize: 18.0);
  ...
} 

但是我发现以下一行有点怪异。

final _biggerFont = const TextStyle(fontSize: 18.0);

我的问题是,将const ant值分配给final变量的目的是什么?

我知道

  

编译时常数被规范化,即不管多少次   您编写const MyObj(0, 0),就只能创建一个对象。

这听起来很有用,但是您可以简单地创建const变量来保存值并使用该变量。

好吧,您不觉得这有点多余吗?我知道Flutter的开发人员想创建一个编译时常量对象,但是,嘿!您正在将该值分配给final变量。有点一样。

有什么想法吗?

更新

我搜索了一些定义,发现

  

const构造函数不能具有主体,并且其类不能具有   任何非最终字段

所以这就是我们使用const关键字的原因吗?因为如果您看一下TextStyle类的设计,您会意识到他们在这里所做的完全相同。

2 个答案:

答案 0 :(得分:1)

我个人认为

final _biggerFont = const TextStyle(fontSize: 18.0);

看起来像一个错误,仅此一个理由就足以改变它。

该成员仅在同一类中使用,因此没有理由不使其成为static。这样,该类的每个实例都不会占用一个额外的内存位置,它们都指向相同的值。 (这是假设编译器无法将字段识别为始终具有相同的值,而只是在各处插入该值)。

如果成员是static,那么它也可能也是const,因此我将其写为:

static const _biggerFont = TextStyle(fontSize: 18.0);

这假设代码是我通过搜索final _biggerFont = const找到的。

如果同一库中有一个覆盖_bifferFont的子类,则它确实需要是一个实例变量。这样,它仍然可能是一个吸气剂,而不是一个字段。效率的提高取决于类的使用方式,以及编译器对总是具有相同值的最终字段进行优化的程度。

在任何情况下,创建始终具有相同常量值的私有实例成员看起来像应该只是一个静态常量,而看起来像是错误的代码却让人难以理解。出于这个原因,我将其重写(或记录下来),以避免读者对它的原样感到困惑。

答案 1 :(得分:0)

const的值是规范的。

这意味着无论您的代码多久包含一次

final _biggerFont = const TextStyle(fontSize: 18.0);

只有一个const TextStyle(fontSize: 18.0)实例。

在类的字段中使用const需要static,这将不允许使用对RandomWordsState实例的引用来访问其值。

具有const构造函数的类有不同的首选项

http://dart-lang.github.io/linter/lints/avoid_field_initializers_in_const_classes.html

  

在const类中避免字段初始化。

     

您应该编写get x => const而不是final x = const expr;   expr;而不分配无用的字段。截至2018年4月,这是事实   用于VM,但不适用于将要编译为JS的代码。

和顶级字段

http://dart-lang.github.io/linter/lints/prefer_const_declarations.html

  

使用const进行const声明的预引用。

     

const声明对热重载更为友好,并允许使用const   构造函数,如果实例化引用了此声明。

对于使用常量值初始化的局部变量,IDE还建议将final替换为const

enter image description here

我还没有找到这个建议的来源,但这是有道理的,因为局部变量可以是const而没有static