【问题标题】:How to use factory const constructors?如何使用工厂常量构造函数?
【发布时间】:2016-07-31 18:16:36
【问题描述】:

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

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 构造函数使其不可变?如果是这样,为什么?

我还要提到,如果传递的值为 null,我曾经抛出错误,但我将其默认为零,因此我实际上可以使用初始化列表。然后我尝试这样做,结果证明当构造函数不是工厂时它可以工作:

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,它不会对构造函数参数进行任何类型的 null 验证或计算,完全依赖于方法会在某个时候在 null-向量。它还有一个构造函数,可以从另一个性能较差且重复性较差的单位向量中创建一个单位向量,这要归功于强制性的初始化列表:

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 新手的警告:C++ 中的 const = 不变性保证。 JS 中的 const = 常量引用。 dart 中的 const = 编译时优化。

标签: constructor dart constants factory


【解决方案1】:

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

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

【讨论】:

  • 我是这么认为的。在这种情况下,我将摆脱 const,让我的类变得不那么健壮似乎不合逻辑。
  • 如果你想让实例不可变,类不需要是常量,只是没有办法修改它的数据字段。
  • 是的,我知道这一点,我只是认为用 const 优化会很好。但我可能太早尝试优化,我应该现在做一个游戏:)
  • 现在是 2020 年,我想确认 const 在 Flutter 中的重要性。我已经看到 const 的大量使用,它似乎对性能优化很重要。这是真的吗?
  • const 被认为会带来更好的性能,但不久前还进行了讨论,并没有找到太多的证据(基准)。像往常一样,性能很大程度上取决于您的具体情况。如果您有一个复杂的应用程序,而这实际上很重要,请确保您自己进行适当的基准测试,以确保您使用正确的措施针对正确的事情进行优化。
猜你喜欢
  • 1970-01-01
  • 2012-02-11
  • 2012-01-31
  • 2020-08-16
  • 2015-06-02
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多