dart - 命名构造函数是 Dart 中生成构造函数的子集吗?

标签 dart constructor

Dart language tour对于构造函数,它给出了一个生成构造函数的例子:

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;
  }
}
稍后它给出了 named constructor 的示例:
class Point {
  double x, y;

  Point(this.x, this.y);

  // Named constructor
  Point.origin() {
    x = 0;
    y = 0;
  }
}
这让我相信,当构造函数使用与类相同的名称时,它就是生成构造函数:
Point(this.x, this.y);
但是当有一个额外的标识符时,它就是一个命名构造函数:
Point.origin() {
  x = 0;
  y = 0;
}
然而,在另一个 my answers Dart 专家将我的“命名构造函数”改为“生成构造函数”。这让我意识到我可能误解了它们之间的区别。命名构造函数是生成构造函数的子集吗?如果是这样,我如何调用一个只有类名而没有附加标识符的构造函数?
language spec 中似乎没有术语“命名构造函数”。 .

最佳答案

在 Dart 中,任何构造函数要么是生成构造函数,要么是工厂构造函数。
如果它说 factory在前面,它是一个工厂构造函数,否则它是一个生成构造函数。
生成构造函数总是创建它所属的精确类的新实例。
工厂构造函数(几乎)只是一个静态函数,其返回类型是它所属的类的类型。它可以返回任何子类型,但它本身不会创建任何新对象。
构造函数可以命名或不命名。对于类(class)Foo ,构造函数名为 Foo是“未命名”(或者,实际上是“空名”)构造函数,Foo.someName是一个命名的构造函数。构造函数是命名还是未命名与它是生成式还是工厂无关。
Dart 没有重载(在同一范围内具有相同名称的多个声明,通常由参数类型区分),因此如果没有命名构造函数,每个类只能有一个构造函数。命名构造函数允许一个类拥有任意数量的构造函数,并且每个构造函数都可以是语言允许的构造函数的任何变体。
构造函数可以是转发的,也可以是非转发的,因为没有更好的名称。
转发生成构造函数必须转发到同一类的生成构造函数。例子:

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.
}
转发工厂构造函数将其参数转发给不同的构造函数。例子:
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.
}
生成和工厂这两种转发构造函数并没有真正的关系。它们以完全不同的方式工作,但都将返回对象的工作委托(delegate)给另一个构造函数,并且它们不能有主体。同样,被命名与所有这些无关。
最后,构造函数可以是const或不。
一个 const 生成构造函数正在转发到另一个 const 生成构造函数,并且 : this(...)参数必须是潜在的常量表达式,或者它是非转发的,然后所有初始化表达式必须是潜在的常量表达式,并且不能有主体。
一个 const 工厂构造函数必须转发给另一个 const 构造函数(无论是工厂的还是生成的)。 const 构造函数不能有主体,非转发工厂构造函数必须有主体。
在所有这些不同的构造函数中,只有非转发生成构造函数可以实际创建一个新对象本身。这就是真正的行动发生的地方。这是最基本的构造函数,它看起来像:
  Foo.bar(this.value, int otherValue) : _otherValue = otherValue, super.bar(42) {
    this.doSomething();
  }
非重定向工厂构造函数是唯一可以使用初始化形式的地方(this.value 形式的参数)。初始化器列表可以初始化在同一类中声明的实例变量,但如果没有,则显然可以为空。最后的超调用必须调用父类(super class)的生成构造函数,但默认为super()如果省略。主体是新对象可用的第一个位置(如 this ),但如果主体为空,则可以省略(替换为 ; )。这就是为什么最简单的构造函数只是 Foo(); (如果您没有声明其他构造函数,这也是您获得的默认构造函数)。

关于dart - 命名构造函数是 Dart 中生成构造函数的子集吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63313102/

相关文章:

dart - 如何改变showMenu下PopupMenuItem的背景颜色?

dart - 在 StreamBuilder 中使用 SnackBar 的奇特方式是什么?

java - 在Java中创建没有构造函数的子类实例

c++ - `print` 具有两个不同构造函数的对象的函数

C++11 将 vector 传递给构造函数

dart - 如何在 Dart 的 paper-input 中获得值(value)?

flutter - 添加容器颜色时出错: Incorrect use of ParentDataWidget

dart - 如何在本地开发Dart库?

c++ - 当我抛出异常时内存是否被释放?

c# - 当两个重载具有相同的签名时调用构造函数重载