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 (i.e. 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. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With