constructor - 如何使用工厂常量构造函数?

标签 constructor dart constants factory

为了测试我对 Dart 的理解,我制作了一个 2D 不可变向量,它不仅存储它的 x 和 y 分量,还存储它的角度和长度。它们仅在构造 x 和 y 值时计算。我很快意识到最终字段需要使用初始值设定项列表或 this 参数快捷方式进行设置,这些快捷方式不允许太多计算值。喜欢this answer指出,我必须使用工厂构造函数从 x 和 y 分量创建向量。然后,工厂构造函数在调用私有(private)构造函数之前验证输入并计算长度和角度。

import 'dart:math';

class ImmutableVector {

  // private fields
  final double _x;
  final double _y;
  final double _angle;
  final double _length;

  // getters
  double get x => _x;
  double get y => _y;
  double get angle => _angle;
  double get length => _length;

  /// Constructs a vector out of cartesian components.
  /// 
  /// Converts both arguments to doubles.
  /// Null values will be treated as zeroes.
  factory ImmutableVector.xy(num x, num y) {

    x ??= 0.0;
    y ??= 0.0;
    x = x.toDouble();
    y = y.toDouble();
    var angle = atan2(y, x) % (2*PI);
    var length = sqrt(pow(x, 2) + pow(y, 2));

    return new ImmutableVector._raw(x, y, angle, length);
  }

  /// Constructs a vector by setting the fields directly.
  const ImmutableVector._raw(this._x, this._y, this._angle, this._length);
}

但我注意到我无法将工厂构造函数设置为 const,因为 const 工厂只能重定向构造函数。是否绝对没有办法让我的向量在其构造函数中包含代码,并且仍然具有 const 构造函数的不可变性?如果是这样,为什么?

我还要提到,如果传递的值为空,我过去会抛出错误,但我将其默认为零,这样我实际上可以使用初始值设定项列表。然后我尝试这样做,结果发现当构造函数不是工厂时它可以工作:

ImmutableVector.xy(num x, num y) : this._raw(
       x = (x ?? 0.0).toDouble(),
       y = (y ?? 0.0).toDouble(),
       atan2(y, x) % (2*PI),
       sqrt(pow(x, 2) + pow(y, 2)));

但是当我尝试将其设置为 const 时,它告诉我初始化列表中的代码包含非编译时常量。

我在 dart 中能找到的唯一不可变向量是 here on GitHub ,并且它不会对构造函数参数进行任何类型的空验证或计算,完全依赖于方法将在空向量上的某个点中断的事实。它还有一个构造函数,可以从另一个单位向量中创建一个单位向量,但由于强制初始化列表,性能较差且重复:

const Vector.unit(final num x, final num y, final num z) : 
    this(x / PMath.len(x, y, z), y / PMath.len(x, y, z), z / PMath.len(x, y, z));

那么我的结论应该是什么?我是否错过了一个使这成为可能的功能,或者我应该放弃在此类中使用 const 吗?

最佳答案

Dart 在编译期间不会执行 Dart 代码。这就是 const 构造函数不能有主体的原因,也是没有其他方法可以解决此限制的原因。

如果您想在创建实例时执行代码,请不要使用const。无论如何,Const 在 Dart 中并不是那么重要。甚至有人讨论将其从语言中删除,因为好处不够大。

关于constructor - 如何使用工厂常量构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36534233/

相关文章:

c++ - 构造函数的显式关键字的使用

java - Android 上的 Flutter VoIP 推送通知

c++ - 选择模板参数不同的模板类构造器导致编译失败

c++ - 在 C++ 构造函数失败的情况下处理多个动态资源解除分配

flutter - 如何在“flutter ”中较小行内的中心对齐大图标?

char * 设置为字符串文字时的编译器警告

C++ - 返回 const 对象的 const vector 的 const vector

.net - 为什么 .Net 中的常量不是全部大写?

javascript - new Function() 和 new Function()() 之间的区别

gridview - 以网格为中心的 flutter 布局