如何在构造函数中初始化 final class 属性?
How do I initialize a final class property in a constructor?
在 Java 中,您可以这样做:
class A {
private final int x;
public A() {
x = 5;
}
}
在 Dart 中,我试过:
class A {
final int x;
A() {
this.x = 5;
}
}
我遇到两个编译错误:
The final variable 'x' must be initialized.
和
'x' can't be used as a setter because its final.
有没有办法在 Dart 的构造函数中设置最终属性?
您不能在构造函数主体中实例化最终字段。有一个特殊的语法:
class Point {
final num x;
final num y;
final num distanceFromOrigin;
// Old syntax
// Point(x, y) :
// x = x,
// y = y,
// distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
// New syntax
Point(this.x, this.y) :
distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
}
您可以在构造函数中使用 this.
语法使其更短(在 https://www.dartlang.org/guides/language/language-tour#constructors 中描述):
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(this.x, this.y)
: distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
}
如果你有一些更复杂的初始化你应该使用工厂构造函数,代码变成:
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point._(this.x, this.y, this.distanceFromOrigin);
factory Point(num x, num y) {
num distance = distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
return new Point._(x, y, distance);
}
}
我在这里进退两难,我想初始化一个没有项目的最终列表,并在构造函数中定义一个 Stream
(就像本例中的 distanceFromOrigin
)。
我无法用下面的任何答案做到这一点,但我将它们混合在一起并且有效。
示例:
class MyBloc {
final BehaviorSubject<List<String>> itemsStream;
final List<String> items = [];
MyBloc() : this.itemsStream = BehaviorSubject<List<String>>.seeded([]) {
items.addAll(List.generate(20, (index) => "Hola! I'm number $index"));
itemsStream.add(items);
}
}
我遇到了类似的问题:我试图从构造函数初始化一个 final
字段,同时调用超级构造函数。你可以想到下面的例子
class Point2d {
final int x;
final int y;
Point2d.fromCoordinates(Coordinates coordinates)
: this.x = coordinates.x,
this.y = coordinates.y;
}
class Point3d extends Point2d {
final int z;
Point3d.fromCoordinates(Coordinates coordinates)
:this.z = coordinates.z,
super.fromCoordinates(coordinates);
}
/// Demo class, to simulate constructing an object
/// from another object.
class Coordinates {
final int x;
final int y;
final int z;
}
很显然这行得通。您可以使用上述语法(检查 Point3d 的构造函数)初始化最终字段,它工作得很好!
运行一个这样的小程序来检查:
void main() {
var coordinates = Coordinates(1, 2, 3);
var point3d = Point3d.fromCoordinates(coordinates);
print("x: ${point3d.x}, y: ${point3d.y}, z: ${point3d.z}");
}
应该是x: 1, y: 2, z: 3
这里是初始化最终 class 变量的方法的简要总结。
class MyClass {
final int x; // <-- initialize this
}
初始化值
class MyClass {
final int x = 'hello'.length;
}
如果只能在运行时进行初始化,则只能使用 final
。否则,static const
更好:
class MyClass {
static const int x = 0;
}
正式的初始化程序
class MyClass {
MyClass(this.x);
final int x;
}
这是最常见的方法。
初始化器列表
class MyClass {
MyClass(int x)
: _x = x;
final int _x;
}
当您想将字段保密时,这很有用。
默认参数值
对于未命名参数,您可以用方括号 ([]
) 将参数括起来,对于命名参数,可以用大括号 ({}
) 括起来,然后给它一个默认值。
class MyClass {
MyClass({this.x = 0});
final int x;
}
如果您想使参数可选,这很有用。
您也可以使用初始化列表完成同样的事情:
class MyClass {
MyClass({int? x})
: _x = x ?? 0;
final int _x;
}
延迟初始化
class MyClass {
MyClass(String? a) {
x = a?.length ?? 0;
}
late final int x;
}
如果您需要执行比初始化列表中允许的更复杂的初始化,这将很有用。例如,我在 Flutter 中初始化手势识别器时就这样做了。
延迟初始化
使用 late
的另一个优点是它不会初始化一个值,直到您访问该值。
class MyClass {
late final int x = _doHeavyTask();
int _doHeavyTask() {
var sum = 0;
for (var i = 0; i < 100000000; i++) {
sum += 1;
}
return sum;
}
}
如果您有繁重的计算并且只在绝对需要时调用它,这将非常有用。
这不会初始化 x
:
final myClass = MyClass();
但这确实会初始化 x
:
final myClass = MyClass();
final value = myClass.x;
class A{
final int x;
A(this.x){
}
}
在 Java 中,您可以这样做:
class A {
private final int x;
public A() {
x = 5;
}
}
在 Dart 中,我试过:
class A {
final int x;
A() {
this.x = 5;
}
}
我遇到两个编译错误:
The final variable 'x' must be initialized.
和
'x' can't be used as a setter because its final.
有没有办法在 Dart 的构造函数中设置最终属性?
您不能在构造函数主体中实例化最终字段。有一个特殊的语法:
class Point {
final num x;
final num y;
final num distanceFromOrigin;
// Old syntax
// Point(x, y) :
// x = x,
// y = y,
// distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
// New syntax
Point(this.x, this.y) :
distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
}
您可以在构造函数中使用 this.
语法使其更短(在 https://www.dartlang.org/guides/language/language-tour#constructors 中描述):
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point(this.x, this.y)
: distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
}
如果你有一些更复杂的初始化你应该使用工厂构造函数,代码变成:
class Point {
final num x;
final num y;
final num distanceFromOrigin;
Point._(this.x, this.y, this.distanceFromOrigin);
factory Point(num x, num y) {
num distance = distanceFromOrigin = sqrt(pow(x, 2) + pow(y, 2));
return new Point._(x, y, distance);
}
}
我在这里进退两难,我想初始化一个没有项目的最终列表,并在构造函数中定义一个 Stream
(就像本例中的 distanceFromOrigin
)。
我无法用下面的任何答案做到这一点,但我将它们混合在一起并且有效。
示例:
class MyBloc {
final BehaviorSubject<List<String>> itemsStream;
final List<String> items = [];
MyBloc() : this.itemsStream = BehaviorSubject<List<String>>.seeded([]) {
items.addAll(List.generate(20, (index) => "Hola! I'm number $index"));
itemsStream.add(items);
}
}
我遇到了类似的问题:我试图从构造函数初始化一个 final
字段,同时调用超级构造函数。你可以想到下面的例子
class Point2d {
final int x;
final int y;
Point2d.fromCoordinates(Coordinates coordinates)
: this.x = coordinates.x,
this.y = coordinates.y;
}
class Point3d extends Point2d {
final int z;
Point3d.fromCoordinates(Coordinates coordinates)
:this.z = coordinates.z,
super.fromCoordinates(coordinates);
}
/// Demo class, to simulate constructing an object
/// from another object.
class Coordinates {
final int x;
final int y;
final int z;
}
很显然这行得通。您可以使用上述语法(检查 Point3d 的构造函数)初始化最终字段,它工作得很好!
运行一个这样的小程序来检查:
void main() {
var coordinates = Coordinates(1, 2, 3);
var point3d = Point3d.fromCoordinates(coordinates);
print("x: ${point3d.x}, y: ${point3d.y}, z: ${point3d.z}");
}
应该是x: 1, y: 2, z: 3
这里是初始化最终 class 变量的方法的简要总结。
class MyClass {
final int x; // <-- initialize this
}
初始化值
class MyClass {
final int x = 'hello'.length;
}
如果只能在运行时进行初始化,则只能使用 final
。否则,static const
更好:
class MyClass {
static const int x = 0;
}
正式的初始化程序
class MyClass {
MyClass(this.x);
final int x;
}
这是最常见的方法。
初始化器列表
class MyClass {
MyClass(int x)
: _x = x;
final int _x;
}
当您想将字段保密时,这很有用。
默认参数值
对于未命名参数,您可以用方括号 ([]
) 将参数括起来,对于命名参数,可以用大括号 ({}
) 括起来,然后给它一个默认值。
class MyClass {
MyClass({this.x = 0});
final int x;
}
如果您想使参数可选,这很有用。
您也可以使用初始化列表完成同样的事情:
class MyClass {
MyClass({int? x})
: _x = x ?? 0;
final int _x;
}
延迟初始化
class MyClass {
MyClass(String? a) {
x = a?.length ?? 0;
}
late final int x;
}
如果您需要执行比初始化列表中允许的更复杂的初始化,这将很有用。例如,我在 Flutter 中初始化手势识别器时就这样做了。
延迟初始化
使用 late
的另一个优点是它不会初始化一个值,直到您访问该值。
class MyClass {
late final int x = _doHeavyTask();
int _doHeavyTask() {
var sum = 0;
for (var i = 0; i < 100000000; i++) {
sum += 1;
}
return sum;
}
}
如果您有繁重的计算并且只在绝对需要时调用它,这将非常有用。
这不会初始化 x
:
final myClass = MyClass();
但这确实会初始化 x
:
final myClass = MyClass();
final value = myClass.x;
class A{
final int x;
A(this.x){
}
}