当前位置: 首页 > 知识库问答 >
问题:

什么时候应该在省道中使用最终字段、工厂构造函数或带有getter的私有字段?

益麻雀
2023-03-14

如果你能弄清楚如何重命名这个问题,我愿意接受建议。

在Dart语言中,可以编写一个包含最终字段的类。这些字段只能在构造函数体运行之前设置。这可以是在声明(通常用于类内的静态常量)上,在声明构造函数或使用 this.field 速记时,在初始化器列表语法中:

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

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

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);
}

几年前,当我尝试学习飞镖时,我也遇到了类似的挫折,现在我有了更多的行李,我仍然不知道。更聪明的方法是什么?

共有2个答案

汤跃
2023-03-14

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

在可能的情况下,将字段设置为final是很好的,如果不可能,则使用公共getter将其设置为私有是一个很好的选择。这是您的选择,因为维护类的是您,其他人不需要查看公共API。

如果你需要复杂的计算,Günther Zöchbauer的建议是第一个:使用辅助函数。在某些情况下,甚至可以内联执行

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后面-这是实现和可维护性的选择,而您是维护代码的人。只要您保持抽象干净,并跟踪您向用户promise的内容(生成构造函数?常量构造函数?)所以您不会破坏它,您可以随时更改实现。

宋景福
2023-03-14

工厂构造函数是一种很好的方法,它允许无限制地预先计算任何值,然后将其传递给普通构造函数以转发到最终字段。

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

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

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

飞镖板示例

 类似资料:
  • 问题内容: 为什么将只有私有构造函数的类标记为final是一个好习惯?我的猜测是,要让其他程序员知道它不能被子类化。 问题答案: 将类定为final具有一些(小的)性能提升,因为JIT编译器可以内联该类的功能。我不知道这是否符合“良好做法”的要求,但是我看到了好处。

  • 问题内容: 假设有一个类,其所有构造函数都声明为private。 例如。: 据我所知,将所有构造函数设为私有类似于将类“ This”声明为 final ,因此无法进行扩展。 但是,我收到的Eclipse消息给我的印象是这是可能的-可以扩展全构造函数私有类。看看这个: 当我尝试使用类似的方法扩展此类时 Eclipse给了我一个错误:“ 隐式超级构造函数This()对于默认构造函数不可见。必须定义一个

  • 定义不可变类的策略表明 所有字段都应该是最终字段。 对于ex: 为什么一定要最终决定? 因为我没有给出setter方法吗?它不能改变。谢谢。

  • 我有一个用例,其中我正在使用一个实用程序类(类中包含的方法都是静态的,构造函数也是私有的)。因此,我不是在创建类的对象,我只是在访问具有类名的方法。因此,在utility类中,我希望访问。但是和自动都不起作用。它总是返回。 是否有方法访问实用工具类中的中的字段?我找了很多,但没有找到任何参考资料。

  • 假设有一个类,其所有构造函数都声明为private。 如。: 据我所知,将所有构造函数私有化类似于将类“This”声明为final——因此它不能被扩展。 然而,我收到的Eclipse消息给我的印象是这是可能的——一个all constructors私有类可以扩展。看看这个: 当我试图用类似于 Eclipse给我一个错误:“隐式超级构造函数This()对默认构造函数不可见。必须定义显式构造函数。"

  • 在下面的代码片段中,变量服务和查询是私有的。 保持它们私有有什么用? 有什么帮助? 注意:我已经阅读了多个与堆栈溢出相关的问题和答案,但找不到任何有效的答案。