首页 > 解决方案 > 在 Dart 类构造函数中使用可选命名参数的正确方法

问题描述

飞镖菜鸟在这里。我已经定义了一个类如下:

class Balance{
  String ccy;
  late Money receivable;
  late Money payable;
  Balance(this.ccy, {Money? receivable, Money? payable}){
   this.receivable = receivable??Money.from(0, code:ccy);
   this.payable = payable??Money.from(0, code:ccy);
  };
}

我将其定义为上述原因是:

  1. 我希望应付账款和应收账款字段永远不会为空,但同时,我不想在创建 Balance 对象时始终为这些字段传递值。
  2. 我希望 ccy 参数是必需的,并使用该参数将应付账款和应收账款字段初始化为 0。

这是定义 Balance 类的正确方法吗?有没有更好的办法?

标签: dart

解决方案


编写此代码的惯用方式是:

class Balance{
  final String currency;
  final Money receivable;
  final Money payable;
  Balance(this.currency, {Money? receivable, Money? payable}) 
      : receivable = receivable ?? Money.from(0, code: currency),
        payable = payable ?? Money.from(0, code: currency);
}

(加上文档!)

通过初始化初始化列表中的字段(正是因为这个原因而存在),您可以使字段最终且不可为空,并且仍然使用依赖于参数的计算来初始化它们。

我永远不会late用于公共领域。在这种情况下,您实际上确实在构造函数中立即对其进行了初始化,因此类的客户端不会在初始化之前意外读取该字段的风险。他们只是不知道,他们所看到的只是场是late. 即使你创建了 field final,一个late final没有初始化器的字段在公共 API 中仍然有一个可见的 setter。

如果您确实希望字段是可变的,那么您可以删除final. late只要您仍然确保在其他人看到对象之前初始化字段,那么存在并没有那么糟糕。然后你仍然通常做我在这里做的事情并避免late.

您可能需要的一种情况late是您需要创建最终字段的循环结构。就像是

class MainNode {
  final String name;
  late final SubNode _sub;
  MainNode(this.name, String data) {
    _sub = SubNode(this, data);
  }
  SubNode get sub => _sub; 
}
class SubNode {
  final MainNode parent;
  String data;
  SubNode(this.parent, this.data);
}

对于这样的事情,您需要在访问创建子节点this,一个late final字段是有意义的,并确保它_sub实际上只写入一次。(不过,我通过将其设为私有来避免_sub在 API 中公开 setter。)


推荐阅读