6

我想重载 Dart 中的比较运算符(==)来比较结构。现在,当我已经重载了基类的比较运算符并想要重用它时,我不确定如何为派生类执行此操作。

假设我有一个基类,例如:

class Base
{
  int _a;
  String _b;

  bool operator ==(Base other)
  {
    if (identical(other, this)) return true;
    if (_a != other._a) return false;
    if (_b != other._b) return false;
    return true;
  }
}

然后我声明我的派生类添加了额外的字段并且还想重载运算符==。我只想比较派生类中的附加字段,并将 Base 字段的比较委托给 Base 类。在其他编程语言中,我可以做类似Base::operator==(other)or的事情super.equals(other),但在 Dart 中,我不知道什么是最好的方法。

class Derived extends Base
{
  int _c; // additional field

  bool operator ==(Derived other)
  {
    if (identical(other, this)) return true;        
    if (_c != other._c) return false; // Comparison of new field

    // The following approach gives the compiler error:
    // Equality expression cannot be operand of another equality expression.
    if (!(super.==(other))) return false;

    // The following produces "Unnecessary cast" warnings
    // It also only recursively calls the Derived operator
    if ((this as Base) != (other as Base)) return false;    

    return true;
  }
}

我想我能做的是:

  • 比较派生类中基类的所有字段:如果基类 get 发生更改,则非常容易出错,并且当基类和派生类位于不同的包中时也不起作用。
  • 声明一个equals与当前在其中具有相同逻辑的函数operator ==,调用super.equals()以比较基类并将所有调用委托operator==给该equals函数。然而,它看起来并不太吸引人来实现equalsoperator ==.

那么这个问题的最佳或推荐解决方案是什么?

4

3 回答 3

9

好的,经过一些进一步的实验,我自己想通了。它只是调用:

super==(other)

我之前super.operator==(other)super.==(other)之前都试过,但没想到简单super==(other)就足够了。

对于上面给出的示例,正​​确的运算符是:

bool operator ==(Derived other)
  {
    if (identical(other, this)) return true;
    if (_c != other._c) return false;
    if (!(super==(other))) return false;
    return true;
  }
于 2013-10-20T14:21:29.000 回答
3

似乎我遇到了一个 5 岁的问题,但现在我们有了 Dart 2 ......

== 运算符可以很容易地内联定义。

class Base {
    int a;
    String b;

    bool operator ==(other) => other is Base
          && other.a == a
          && other.b == b;
}

从派生类重用,super == other似乎仍然是这种方式。

class Derived extends Base {
    int c;

    bool operator ==(other) => other is Derived
          && super == other
          && other.c == c;
}

话虽如此,我发现了一个主要问题,所调用的 == 运算符似乎是比较左侧的运算符。那Base == Derived将调用 Base 的 == 比较,而Derived == Base将调用 Derived 的 == 比较(以及随后的 Base)。这似乎是合理的,但让我摸不着头脑。

前任:

main() {
    Base b = new Base();
    Derived d1 = new Derived();
    Derived d2 = new Derived();

    b.a = 6;
    d1.a = 6;
    d2.a = 6;

    b.b = "Hi";
    d1.b = "Hi";
    d2.b = "Hi";

    d1.c = 1;
    d2.c = 1;

    assert(d1 == d2); // pass
    assert(b == d1);  // PASS!!!
    assert(d1 == b);  // fail
}

(注意:出于演示目的,我从字段中删除了私有_。)

于 2018-11-29T17:36:39.647 回答
0

为了避免基类错误地与子类相等的问题,您可以添加对 runtimeType 的附加检查,如下所示。

bool operator ==(other) => other is Base
      && this.runtimeType == other.runtimeType
      && other.a == a
      && other.b == b;
于 2019-09-26T08:31:59.697 回答