I have a late property(_bmi
) set to null by default and then I initialize it in a method calcBMI()
, after its initialization, I use its value in two more methods, result
and interpretation
to fulfill some bool conditions, but I run into a lateinitialisationerror
, because the first method (result()
) doesn’t recognize the value I initialized in calcBMI()
, it rather defaults to the initial null value that the _bmi
property had, however the interpretation()
method recognizes the initialized value. How I know it’s only the first method that doesn’t recognize it is coz when I pass a value to the _bmi
property when I’m setting it, the app doesn’t throw the error, it works, but then it uses the set value for the first method, but the initialised value from calcBMI()
for the second method, what am I doing wrong, here is the code.
class CalculatorBrain {
CalculatorBrain({required this.weight, required this.height});
int weight;
int height;
late double _bmi = 30; // when I set this value, result() works with it, but interpretation() works with the value passed in calcBMI();
String calcBMI() {
_bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
String result() {
if(_bmi >= 25) {
return 'overweight';
} else if(_bmi > 18.5) {
return 'normal';
} else {
return 'underweight';
}
}
String interpretation() {
if(_bmi >= 25) {
return 'You have a higher than normal body weight. Try to exercise more.';
} else if(_bmi > 18.5) {
return 'You have a normal body weight. Good job.';
} else {
return 'You have a lower than normal body weight. You can eat a bit more.';
}
}
}
this is where I use my class
BottomButton(
onTap: () {
CalculatorBrain calc = CalculatorBrain(
weight: weight,
height: height,
);
setState(() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ResultsPage(result: calc.result(), bMI: calc.calcBMI(), interpretation: calc.interpretation());
}
),
);
});
},
title: 'CALCULATE',
),
2
Answers
late modifier means that you will at some point define it, which you are doing in
calcBMI()
, after which you callinterpretation()
where_bmi
already has a value.Your code would crash if you just call
result()
since_bmi
still isn’t defined.If you got a
LateInitializationError
before, it’s not that "[result()
] doesn’t recognize the value I initialized incalcBMI()
", it’s that you calledresult()
before you calledcalcBMI()
.Giving
_bmi
an initial value avoids theLateInitializationError
, but you still have the same fundamental problem: you’re reading_bmi
before you callcalcBMI()
to assign it the value you actually want.In particular, you have:
Dart evaluates function arguments in left-to-right order, so you’ll call
calc.result()
first, thencalc.calcBMI()
, and thencalc.interpretation()
. Changing the order should fix your problem:However, relying on argument evaluation order would be poor style. It would not be obvious to readers (including your future self) that argument order matters. It would be much better to explicitly order operations that are order-dependent:
Note that this has nothing to do with
_bmi
beinglate
. Declaring_bmi
aslate
provides no purpose in your code as currently written, and you could just remove it. But you also should consider rewriting your code to makeCalculatorBrain
less dependent on consumers calling its methods in a particular order. Some possibilities:Compute
_bmi
dynamicallyYou could make
_bmi
a getter that computes the correct value forweight
/height
on every access:Compute
_bmi
exactly onceIf you make
weight
/height
final
, then you can compute_bmi
once and be done:Update
_bmi
automatically ifweight
orheight
changesIf you
weight
/height
must be mutable, then you could create setters so that_bmi
is always updated automatically: