在 Dart 中,如何让重载运算符返回子类类型?

布拉姆

我有两个简单的类:(Point它有一个 x 和 y)和Point3D(它extends Point也有 az 参数)。我想覆盖 + 运算符,以便我可以添加两点。因为 + 运算符需要返回类,所以 Point 中 + 的方法签名与 Point3D 中 + 的签名不同,这在 Dart 中是不允许的。我已经通过一个界面试过了:

abstract class PointOperations<T extends Point> {
   T operator +(T p);
}

并在 Point 和 Point3D 中实现这一点,如下所示:

class Point implements PointOperations<Point> {
  final double x, y;

  Point(this.x, this.y);
    
  @override
  Point operator +(Point p) => Point(x + p.x, y + p.y);
}

class Point3D extends Point implements PointOperations<Point3D>{
  final double z;

  Point3D(double x, double y, this.z) : super(x, y);

  @override
  Point3D operator +(Point3D p) => Point3D(x + p.x, y + p.y, z + p.z);
}

我收到编译错误The class 'Point3D' cannot implement both 'PointOperations<Point>' and 'PointOperations<Point3D>' because the type arguments are different.我理解该错误,但不明白如何在不诉诸具有不同名称的方法(例如Point addPoint(Point p)Point3D addPoint3D(Point3D p))的情况下完成我想要的

我可以使用命名构造函数使其工作:

Point.add(Point a, Point b) : x = a.x + b.x, y = a.y + b.y;

Point3D.add(Point3D a, Point3D b) : z = a.z + b.z, super(a.x + b.x, a.y + b.y);

但这并不优雅,当然也不是运算符重载。有没有办法做到这一点?

布拉姆

我想我想通了。Point我定义:

Point operator +(covariant Point p) => Point(x + p.x, y + p.y);

将参数定义为 acovariant允许子类在Point3D没有冲突的情况下使用该参数Point3D我定义:

@override
Point3D operator +(Point3D p) => Point3D(x + p.x, y + p.y, z + p.z);

返回类型有效,因为它是Point.

请注意,可以使用以下替代方法:

@override
Point3D operator +(Point p) => Point3D(x + p.x, y + p.y, z + (p as Point3D).z);

where 需要您强制转换Point pto access z,但是如果您想将 a 添加Point到 a Point3D(这将需要额外的类型检查并且不是我正在寻找的,但可以想象这样做并设置z为 0 如果p是),这可能很有用一个Point而不是Point3D)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章