代码之家  ›  专栏  ›  技术社区  ›  Domino

dart中何时应该使用final字段、工厂构造函数或带有getter的私有字段?

  •  1
  • Domino  · 技术社区  · 7 年前

    如果你能想出如何重新命名这个问题,我愿意接受建议。

    在建造师之前 this.field 速记:

    class NumBox{
      final num value;
      NumBox(this.value);
    }
    

    比如说,我实际上需要对实例创建进行一些处理,不能在构造函数之前初始化字段。我可以切换到使用带有getter的私有非final字段:

    class NumBox{
      num _value;
      NumBox(num v) {
        _value = someComplexOperation(v);
      }
      num get value => _value;
    }
    

    或者我可以使用工厂构造函数获得类似的行为:

    class NumBox{
      final num value;
      factory NumBox(num v) {
        return new NumBox._internal(someComplexOperation(v));
      };
      NumBox._internal(this.value);
    }
    

    几年前我试着学习Dart时也遇到了类似的问题,现在我有了更多的行李,我仍然不知道。

    2 回复  |  直到 7 年前
        1
  •  5
  •   Günter Zöchbauer    7 年前

    另一种方法是在构造函数主体之前执行初始化器列表,因此允许初始化最终字段:

    class NumBox{
      final num value;
      NumBox(num v) : value = someComplexOperation(v)
    }
    

    在初始值设定项列表中,不允许您阅读 this 因为实例尚未完全初始化。

    DartPad example

        2
  •  3
  •   lrn    7 年前

    您应该在设计API时考虑到您的用户,然后以任何更简单、更易于维护的方式实现它。这个问题是关于后一部分的。

    如果可能的话,让fields成为final是很好的选择,如果不可能的话,让fields成为公共getter的私人成员是一个很好的选择。做什么是你的选择,因为维护类的是你,其他人不需要查看公共API。

    class MyThing {
      final x;
      MyThing(args) : x = (() { complex code on args; return result;} ());
    }
    

    不过,它很快就会变得丑陋,因此将其作为静态辅助函数通常更好。

    工厂构造函数是一种简单的方法,您可以计算所需的一切,然后在最后调用私有生成构造函数。唯一的“问题”是,通过不公开生成构造函数,您会阻止其他人扩展您的类。我引用“问题”是因为这不一定是坏事——允许人们扩展类是一种合同,它限制了你可以用类做什么。 我倾向于使用公共工厂构造函数和私有生成构造函数,即使出于任何实际原因不需要,只是为了禁用类扩展。

    class MyClass {   
      const factory MyClass(args) = MyClass._; // Can be const, if you want it.
      const MyClass._(args) : ... init .. args ...;
    }
    

    需要

    class MyClass {
      final This x;
      final That y;
      MyClass(args) : this._(args, _complexComputation(args));
      MyClass._(args, extra) : x = extra.theThis, y = extra.theThat, ...;
    }
    

    总之,没有严格的规定。如果你喜欢final字段,你可以做额外的工作使它们成为final,或者你可以把易变性隐藏在getter后面——这是一个实现和可维护性的选择,而你是维护代码的人。 只要您保持抽象干净,并跟踪您向用户承诺的内容(生成构造函数?const构造函数?)因此,您不会破坏这一点,您可以随时更改实现。