在构造器的Dart 语言之旅中,它给出了一个生成式构造器的示例:
class Point {
double x, y;
Point(double x, double y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}
Run Code Online (Sandbox Code Playgroud)
后来它给出了一个命名构造函数的例子:
class Point {
double x, y;
Point(this.x, this.y);
// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}
Run Code Online (Sandbox Code Playgroud)
这让我相信,当构造函数使用与类相同的名称时,它是一个生成构造函数:
Point(this.x, this.y);
Run Code Online (Sandbox Code Playgroud)
但是当有一个额外的标识符时,它就是一个命名构造函数:
Point.origin() {
x = 0;
y = 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,在我的另一个答案中,Dart 专家将我的“命名构造函数”更改为“生成构造函数”。这让我意识到我可能误解了它们之间的区别。命名构造函数是生成构造函数的子集吗?如果是这样,我如何调用只有类名而没有附加附加标识符的构造函数?
术语“命名构造函数”似乎不在语言规范中。
lrn*_*lrn 12
在 Dart 中,任何构造函数要么是生成构造函数,要么是工厂构造函数。如果factory前面有写,就是工厂构造函数,否则就是生成构造函数。
生成构造函数总是创建它所属的精确类的新实例。工厂构造函数(几乎)只是一个静态函数,其返回类型是它所属类的类型。它可以返回它的任何子类型,但它本身不会创建任何新对象。
构造函数可以是named或unnamed。对于 class Foo,命名的构造函数Foo是“未命名”(或者,实际上,“空命名”)构造函数,并且Foo.someName是命名构造函数。构造函数是命名的还是未命名的与它是生成式还是工厂无关。Dart 没有重载(在同一范围内有多个具有相同名称的声明,通常由参数类型区分),因此如果没有命名构造函数,每个类只能有一个构造函数。命名构造函数允许一个类拥有任意数量的构造函数,并且每个构造函数都可以是该语言允许的构造函数的任何变体。
构造函数可以是forwarding,也可以是non-forwarding,因为没有更好的名称。转发生成构造函数必须转发到同一类的生成构造函数。例子:
class Point {
final double x, y;
const Point(this.x, this.y); // Generative, unnamed, non-forwarding, const.
const Point.diagonal(double xy) : this(xy, xy); // Generative, named, forwarding, const.
}
Run Code Online (Sandbox Code Playgroud)
转发工厂构造函数将其参数转发给不同的构造函数。例子:
abstract class Point {
double get x;
double get y;
const factory Point(this.x, this.y) = _Point; // Factory, unnamed, forwarding, const.
}
class _Point implements Point {
final double x, y;
const _Point(this.x, this.y); // Generative, unnamed, non-forwarding, const.
}
Run Code Online (Sandbox Code Playgroud)
这两种转发构造函数,generative 和 factory,并没有真正的关联。它们以完全不同的方式工作,但都将返回对象的工作委托给另一个构造函数,并且它们不能有一个主体。同样,命名与所有这些无关。
最后,构造函数可以是也可以const不是。const 生成构造函数要么转发到另一个 const 生成构造函数,并且: this(...)参数必须是潜在的常量表达式,要么是非转发的,然后所有初始化表达式必须是潜在的常量表达式并且不能有主体。const 工厂构造函数必须转发到另一个 const 构造函数(无论是工厂还是生成)。const 构造函数不能有主体,非转发工厂构造函数必须有主体。
在所有这些不同的构造函数中,只有非转发生成构造函数才能真正创建一个新对象本身。这就是真正的行动发生的地方。这是最基本的构造函数,它看起来像:
Foo.bar(this.value, int otherValue) : _otherValue = otherValue, super.bar(42) {
this.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
非重定向工厂构造函数是唯一可以使用初始化形式(形式的参数this.value)的地方。初始化列表可以初始化在同一个类中声明的实例变量,但如果没有,显然可以为空。最后的超调用必须调用超类的生成构造函数,但super()如果省略则默认为。正文是新对象可用的第一个位置(作为this),但如果正文为;空,则可以省略(由 替换)。这就是为什么最简单的构造函数只是Foo();(如果您没有声明其他构造函数,这也是您获得的默认构造函数)。
| 归档时间: |
|
| 查看次数: |
565 次 |
| 最近记录: |