简体   繁体   中英

When is it nesessary to use final for variables in flutter (dart)

I am confused as to when its compulsory to use final for variables.

According to documents and answers on StackOverflow,

If you make a StatefulWidget subclass with non-final fields, it will result in DartAnalysis warning

But I made this class and everything runs fine

class Order extends StatefulWidget {
  int hello = 1;

  @override
  _OrderState createState() => _OrderState();
}

class _OrderState extends State<Order> {
  pizza _pizzaOrder = new pizza();

  void setSize(String value) {
    setState(() {
      _pizzaOrder.size = value;
      print(++widget.hello);
    });
  }

I made a simple app and never used final or const anywhere in the program. So is it compulsory anywhere that I must use "final"/"const"? Or is just for optimization? And when should I use "final"?

I think this is more related to the OOP principle SOLID , specifically open/close principle.

When you build a widget some cases you need some parameters to your constructor in order to define the attributes of your class. If you don't use final to your attribute, then it can be modified by other classes including the state.

In your case:

print(++widget.hello);

It works but it can cause unexpected behavior, imagine many classes accessing that attribute and modifying it, don't you want that right?

I found another reason StatefulWidget

StatefulWidget instances themselves are immutable and store their mutable state either in separate State objects that are created by the createState method, or in objects to which that State subscribes, for example Stream or ChangeNotifier objects, to which references are stored in final fields on the StatefulWidget itself.

Adding to what diegoveloper have already said, imagine that you added a new parameter to the Order StatefulWidget and you're running the app so want it to hot reload.

The order widget will be recreated, but as it was a hot reload the State object will remain there with its existing values. In that case, you should be persisting this state in the State object, but in your example, the value in hello will be lost (ie will reset back to 1).

This way you won't lose hello state:

class Order extends StatefulWidget {
  Order({this.hello});
  final int hello;

  @override
  _OrderState createState() => _OrderState();
}

class _OrderState extends State<Order> {
  pizza _pizzaOrder = new pizza();
  int _hello;

  @override
  initState() {
    _hello = widget.hello;
  }

  void setSize(String value) {
    setState(() {
      _pizzaOrder.size = value;
      print(++_hello);
    });
  }

However, let's say in a parent widget you are creating it like this:

Order(hello: 1);

If you change the parent to:

Order(hello: 2);

And then again you hot reload, the parameter is final, and the StatefulWidget gets recreated, the State object is maintained, but then it doesn't update it's value according to the widget's new parameter. For that, you would use didUpdateWidget then:

class Order extends StatefulWidget {
  Order({this.hello});
  final int hello;

  @override
  _OrderState createState() => _OrderState();
}

class _OrderState extends State<Order> {
  pizza _pizzaOrder = new pizza();
  int _hello;

  @override
  initState() {
    _hello = widget.hello;
  }

  @override
  void didUpdateWidget(Order oldWidget) {
    super.didUpdateWidget(oldWidget);
    setState(() {
      _hello = widget.hello;
    });
  }

  void setSize(String value) {
    setState(() {
      _pizzaOrder.size = value;
      print(++_hello);
    });
  }

I deviated a bit from the question, but I thought it was somehow relevant. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM