在Dart中,你能从一个构造函数中调用另一个构造函数吗?

53

也就是说,我正在尝试从一个构造函数中调用另一个构造函数,然后进一步构造。我无法从文档中弄清楚它是否可以完成。

以下是一个人为制造的示例,如果有帮助的话:

class Chipmunk {

  Chipmunk.named(this.name);

  Chipmunk.famous() {
    this.named('Chip');  // <-- What, if anything, goes here?
    this.fame = 1000;   
  }
}

var chip = new Chimpmunk.famous();
3个回答

78

有两种可能的方法来做到这一点:

class Chipmunk {
  String name;
  int fame;

  Chipmunk.named(this.name, [this.fame]);

  Chipmunk.famous1() : this.named('Chip', 1000);

  factory Chipmunk.famous2() {
    var result = new Chipmunk.named('Chip');
    result.fame = 1000;
    return result;
  }
}

Chipmunk.famous1() 是一个重定向构造函数。您无法在这种构造函数中分配属性,因此您调用的构造函数必须允许您设置的所有属性。这就是为什么我添加了可选参数 fame。在这种情况下,您可以使 namefame 成为最终变量。

Chipmunk.famous2() 是一个工厂构造函数,可以创建您想要的实例。在这种情况下,fame 不能被定义为最终变量(显然,如果您在 named 构造函数中使用了 fame 参数,则可以将其定义为最终变量)。

对于您的用例,第一种变体可能更可取。

这是语言规范中的文档:

生成构造函数由构造函数名称、构造函数参数列表和重定向子句或初始化器列表及可选体组成。

https://dart.dev/docs/spec/latest/dart-language-specification.html#h.flm5xvbwhs6u


4
答案在“是”和“否”之间。对我来说有点奇怪的是,重定向构造函数不能有主体。 - Grumdrig
答案肯定是肯定的,而且它也适用于从命名构造函数调用非命名构造函数。 - Giorgio Barchiesi

1
在这里可以使用init模式:构造函数只调用类中定义的一个init函数。
它在某些情况下比重定向构造函数具有优势,我现在能想到两种情况:
- 如果您正在保存/恢复对象的状态(在这种情况下,您只需编写一次恢复部分)。
- 如果您正在池化(回收)对象并且需要在重新启动它们时“刷新”它们。
class Chipmunk {

  Chipmunk.named(string newName) { nameInit(newName) };

  Chipmunk.famous() {
    famousInit();
  }

  nameInit(string newName) {
     name = newName ;
  }

  famousInit() {
    nameInit('Chip');
    fame = 1000;
  }

 string name;
 num fame;
}

var chip = new Chimpmunk.famous();

1
在 Dart 中,有时重用对象可能很有用,但通常不建议这样做。原因是:Dart 运行时高度优化以处理不可变对象。一般来说,如果您只是丢弃一个无效的对象并用新对象替换它,而不是更新对象的内部状态,那么您的应用程序将表现更好。 - Soundbytes

0

另一种方法是使用返回同一类的实例的静态方法。

从技术上讲,它不是构造函数,并且 Dart Linter 不建议 使用它,但在需要根据参数值选择调用哪个构造函数的情况下,它可以提供帮助。

class Chipmunk {
  Chipmunk.named(this.name, [this.fame]);

  // ignore: prefer_constructors_over_static_methods
  static Chipmunk withFame(int fame) {
    if (fame > 100) {
       return Chipmunk.named('Super Famous Chip', fame);
    }
    return Chipmunk.named('Chip', fame);
  }

  String name;
  int? fame;
}

var superFamousChip = Chipmunk.withFame(110);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接