在Dart中修改类内部的最终字段



Dart文档读取:

如果您从未打算更改变量,请使用final或const而不是var或添加到类型中。可以设置最终变量仅一次;

好的,这意味着第二次分配最终变量将不起作用,什么都没有是关于修改的,即

void main() {
  final List<int> list = [1,2,3];  
  list = [10, 9, 8]; //error!
  list
  ..clear()
  ..addAll([10, 9, 8]); //works!
}

可以看出,本质上,I重新分配了最终变量list。这不是与最终变量的整个概念相矛盾吗?

final并不意味着深度final

即使在修改列表内容时,list变量仍然引用相同的列表实例。任何可变实例都可以被修改,即使它被分配给了最终变量。想象一下

void main() {
  var l = [1,2,3];
  final List<int> list = l;  
}

现在,您将无法修改l引用的列表中的项目,因为该列表也被分配给最终字段listlistl都引用相同的列表)。这没有道理。

你可以做什么使列表不可变是

final List<int> list = const[1,2,3];  

现在,您不能将另一个列表分配给list,也不能修改list引用的列表的内容。

的另一种方式

  import 'dart:collection'
  ...
  var l = [1,2,3];
  final List<int> list = UnmodifiablyListView(l);

现在您不能修改listlist引用的列表内容,但可以修改l引用的内容(list将反映对l所做的更改)
如果您丢失了对l的引用,则无法修改内容。

  var l = [1,2,3];
  final List<int> list = UnmodifiablyListView(l);
  l = null;

例如,当您希望确保list字段永远不会设置为null时,final非常好。

class MyModel {
  final list = [];
}

list字段是公共的,但是没有人可以将list设置为例如null

var model = new MyModel();
...
model.list.forEach(print);

除了像CCD_ 23这样的异常,永远不会失败
这与类似,但更简洁

class MyModel {
  var _list = [];
  List get list => _list;
}

这是constfinal的混淆。区别在于:

final-表示您不能使用运算符=。但是您可以添加或删除项目。赋值是最终的,但是,值不是恒定的。

示例:

void main() {
  final List<int> list = [1,2,3];  
  print(list); // [1, 2, 3]
  list.add(5); // Works!
  print(list); // [1, 2, 3, 5]
}

const-意味着您不能重新分配或更改值。

void main() {
  const List<int> list = [1,2,3];  
  print(list); // [1, 2, 3]
  list.add(5); // Uncaught Error: Unsupported operation: add
  print(list);
}

除了Adrian的答案之外,我刚开始使用Dart,我在理解它时遇到了一些困难,直到我自己把它分解了。当最后一个关键字被分配给一个变量(最好在运行时使用)进行初始化时,不能更改它。[它们通常是实例变量]const关键字最好用于类变量(静态const)和声明常量变量。它们在运行时初始化之前根本无法更改。但当我们进入列表时,对final和const的解释会变得更加狭隘。只能使用.add()或.remove()修改最终列表,这意味着赋值是最终的,但值不是const列表,并且不能以任何方式进行突变,它们是最终的,这关闭了初始化列表的使用。我希望这能有所帮助。https://dart.dev/guides/language/language-tour#variables

最新更新