如何正确初始化延迟变量
How do I properly initialize a late variable
我有一个迟到的属性(_bmi
)默认设置为null,然后我在方法calcBMI()
中初始化它,在初始化之后,我将它的值用在两个更多方法,result
和 interpretation
来满足一些布尔条件,但我 运行 变成了 lateinitialisationerror
,因为第一个方法 (result()
) 不识别我在 calcBMI()
中初始化的值,它默认为 _bmi
属性 具有的初始空值,但是 interpretation()
方法识别初始化值。我怎么知道这只是第一个不识别它的方法是因为当我将一个值传递给 _bmi
属性 时,当我设置它时,应用程序不会抛出错误,它有效,但随后它使用第一种方法的设置值,但第二种方法使用 calcBMI()
的初始化值,我做错了什么,这是代码。
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.';
}
}
}
这是我使用 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',
),
late 修饰符意味着您将在某个时候定义它,您在 calcBMI()
中正在这样做,之后您调用 interpretation()
,其中 _bmi
已经有一个值。
如果您只是调用 result()
,您的代码将崩溃,因为 _bmi
仍未定义。
如果你之前有一个LateInitializationError
,那不是“[result()
]无法识别我在calcBMI()
中初始化的值”,而是你调用了[=17] =] 在你打电话给 calcBMI()
.
之前
给 _bmi
一个初始值避免了 LateInitializationError
,但你仍然有同样的基本问题:你正在阅读 _bmi
before 您调用 calcBMI()
为其分配您实际想要的值。
特别是,您有:
return ResultsPage(result: calc.result(), bMI: calc.calcBMI(), interpretation: calc.interpretation());
Dart 按 left-to-right 顺序计算函数参数,因此您将首先调用 calc.result()
,然后是 calc.calcBMI()
,然后是 calc.interpretation()
。更改顺序应该可以解决您的问题:
return ResultsPage(
bMI: calc.calcBMI(),
result: calc.result(),
interpretation: calc.interpretation(),
);
但是,依赖参数评估顺序是一种糟糕的风格。读者(包括你未来的自己)不会明显看出参数顺序很重要。明确排序 order-dependent:
的操作会好得多
var bmi = calc.calcBMI();
return ResultsPage(
result: calc.result(),
bMI: bmi,
interpretation: calc.interpretation(),
);
请注意,这与 _bmi
成为 late
无关。将 _bmi
声明为 late
在您当前编写的代码中没有任何意义,您可以将其删除。但是您还应该考虑重写您的代码,以减少 CalculatorBrain
对消费者以特定顺序调用其方法的依赖。一些可能性:
动态计算_bmi
您可以使 _bmi
成为 getter,在每次访问时计算 weight
/height
的正确值:
class CalculatorBrain {
CalculatorBrain({required this.weight, required this.height});
int weight;
int height;
double get _bmi => weight / pow(height / 100, 2);
String calcBMI() => _bmi.toStringAsFixed(1);
String result() {
final _bmi = this._bmi;
if(_bmi >= 25) {
return 'overweight';
} else if(_bmi > 18.5) {
return 'normal';
} else {
return 'underweight';
}
}
...
恰好计算_bmi
一次
如果你使 weight
/height
final
,那么你可以计算 _bmi
一次并完成:
class CalculatorBrain {
CalculatorBrain({required this.weight, required this.height});
final int weight;
final int height;
// `late` computes `_bmi` lazily, which is necessary because it depends on
// `weight` and `height`.
late final double _bmi = weight / pow(height / 100, 2);
...
如果 weight
或 height
更改
,则自动更新 _bmi
如果 weight
/height
必须是可变的,那么您可以创建设置器以便 _bmi
始终自动更新:
class CalculatorBrain {
CalculatorBrain({required int weight, required int height})
: _weight = weight,
_height = height {
_updateBmi();
}
late double _bmi;
int _weight;
int get weight => _weight;
set weight(int value) {
_weight = value;
_updateBmi();
}
int _height;
int get height => _height;
set height(int value) {
_height = value;
_updateBmi();
}
void _updateBmi() {
_bmi => weight / pow(height / 100, 2);
}
...
我有一个迟到的属性(_bmi
)默认设置为null,然后我在方法calcBMI()
中初始化它,在初始化之后,我将它的值用在两个更多方法,result
和 interpretation
来满足一些布尔条件,但我 运行 变成了 lateinitialisationerror
,因为第一个方法 (result()
) 不识别我在 calcBMI()
中初始化的值,它默认为 _bmi
属性 具有的初始空值,但是 interpretation()
方法识别初始化值。我怎么知道这只是第一个不识别它的方法是因为当我将一个值传递给 _bmi
属性 时,当我设置它时,应用程序不会抛出错误,它有效,但随后它使用第一种方法的设置值,但第二种方法使用 calcBMI()
的初始化值,我做错了什么,这是代码。
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.';
}
}
}
这是我使用 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',
),
late 修饰符意味着您将在某个时候定义它,您在 calcBMI()
中正在这样做,之后您调用 interpretation()
,其中 _bmi
已经有一个值。
如果您只是调用 result()
,您的代码将崩溃,因为 _bmi
仍未定义。
如果你之前有一个LateInitializationError
,那不是“[result()
]无法识别我在calcBMI()
中初始化的值”,而是你调用了[=17] =] 在你打电话给 calcBMI()
.
给 _bmi
一个初始值避免了 LateInitializationError
,但你仍然有同样的基本问题:你正在阅读 _bmi
before 您调用 calcBMI()
为其分配您实际想要的值。
特别是,您有:
return ResultsPage(result: calc.result(), bMI: calc.calcBMI(), interpretation: calc.interpretation());
Dart 按 left-to-right 顺序计算函数参数,因此您将首先调用 calc.result()
,然后是 calc.calcBMI()
,然后是 calc.interpretation()
。更改顺序应该可以解决您的问题:
return ResultsPage(
bMI: calc.calcBMI(),
result: calc.result(),
interpretation: calc.interpretation(),
);
但是,依赖参数评估顺序是一种糟糕的风格。读者(包括你未来的自己)不会明显看出参数顺序很重要。明确排序 order-dependent:
的操作会好得多var bmi = calc.calcBMI();
return ResultsPage(
result: calc.result(),
bMI: bmi,
interpretation: calc.interpretation(),
);
请注意,这与 _bmi
成为 late
无关。将 _bmi
声明为 late
在您当前编写的代码中没有任何意义,您可以将其删除。但是您还应该考虑重写您的代码,以减少 CalculatorBrain
对消费者以特定顺序调用其方法的依赖。一些可能性:
动态计算_bmi
您可以使 _bmi
成为 getter,在每次访问时计算 weight
/height
的正确值:
class CalculatorBrain {
CalculatorBrain({required this.weight, required this.height});
int weight;
int height;
double get _bmi => weight / pow(height / 100, 2);
String calcBMI() => _bmi.toStringAsFixed(1);
String result() {
final _bmi = this._bmi;
if(_bmi >= 25) {
return 'overweight';
} else if(_bmi > 18.5) {
return 'normal';
} else {
return 'underweight';
}
}
...
恰好计算_bmi
一次
如果你使 weight
/height
final
,那么你可以计算 _bmi
一次并完成:
class CalculatorBrain {
CalculatorBrain({required this.weight, required this.height});
final int weight;
final int height;
// `late` computes `_bmi` lazily, which is necessary because it depends on
// `weight` and `height`.
late final double _bmi = weight / pow(height / 100, 2);
...
如果 weight
或 height
更改
,则自动更新 _bmi
如果 weight
/height
必须是可变的,那么您可以创建设置器以便 _bmi
始终自动更新:
class CalculatorBrain {
CalculatorBrain({required int weight, required int height})
: _weight = weight,
_height = height {
_updateBmi();
}
late double _bmi;
int _weight;
int get weight => _weight;
set weight(int value) {
_weight = value;
_updateBmi();
}
int _height;
int get height => _height;
set height(int value) {
_height = value;
_updateBmi();
}
void _updateBmi() {
_bmi => weight / pow(height / 100, 2);
}
...