Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying final fields inside the class in Dart

Dart docs read:

If you never intend to change a variable, use final or const, either instead of var or in addition to a type. A final variable can be set only once;

Ok, this means that assigning a final variable second time will not work, but nothing is said about modifying, i.e.

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

  list = [10, 9, 8]; //error!

  list
  ..clear()
  ..addAll([10, 9, 8]); //works!
}

As one can see, in essence, I re- assigned final variable list. Doesn't it contradict the whole idea of final variables?

like image 699
Victor Ermolaev Avatar asked Oct 07 '14 12:10

Victor Ermolaev


People also ask

Can we change final variable value in Dart?

You can't change the value of a final variable: name = 'Alice'; // Error: a final variable can only be set once. The const keyword isn't just for declaring constant variables. You can also use it to create constant values, as well as to declare constructors that create constant values.

Can a final variable be changed Flutter?

Once assigned a value, a final variable's value cannot be changed. final modifies variables. final should be used over const if you don't know the value at compile time, and it will be calculated/grabbed at runtime. if you have a const collection, everything inside of that is in const.

What is final data type in Dart?

The final keyword is used to hardcode the values of the variable and it cannot be altered in future, neither any kind of operations performed on these variables can alter its value (state).

How do you use the final variable in Flutter?

A variable with the final keyword will be initialized at runtime and can only be assigned for a single time. In a class and function, you can define a final variable. For Flutter specific, when the state is updated, everything in the build method will be initialized again.


1 Answers

final doesn't mean deep final.

The list variable references still the same list instance even when you modify the lists content. Any mutable instance can be modified even when it was assigned to a final variable. Imagine

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

Now you wouldn't be able to modify the items in the list referenced by l because the list is also assigned to the final field list (both list and l reference the same list). That doesn't make sense.

What you can do to make the list immutable is

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

Now you can't assign another list to list and you can't modify the contents of the list referenced by list.

An alternative way

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

Now you can't modify list or the contents of the list referenced by list but you can modify the contents referenced by l (list would reflect the changes made to l).
If you loose the reference to l you have no way of modifying the contents.

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

final is nice when you for example want to ensure that the list field never is set to null.

class MyModel {
  final list = [];
}

The list field is public but nobody can set list to for example null.

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

will never fail with an exception like null doesn't have a method 'forEach'.
This is similar but more concise than

class MyModel {
  var _list = [];
  List get list => _list;
}
like image 82
Günter Zöchbauer Avatar answered Nov 16 '22 02:11

Günter Zöchbauer