我想重载 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;
}
}
然后我声明我派生的类,它添加了额外的字段,并且还想重载 operator==。我只想比较派生类中的其他字段,并将 Base 字段的比较委托给 Base 类。在其他编程语言中,我可以做一些类似Base::operator==(other)
或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;
}
}
我想我能做的是:
- 在派生类中也比较基类
- 的所有字段:如果基类被更改,则非常容易出错,并且当基类和派生类位于不同的包中时也不起作用。
- 声明一个与当前
operator ==
相同的逻辑的equals
函数,调用super.equals()
以比较基类并将所有operator==
调用委托给equals
函数。但是,实施equals
和operator ==
看起来并不太吸引人。
那么这个问题的最佳或推荐解决方案是什么?
好的,经过一些进一步的实验,我自己想通了。它只是在调用:
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;
}
似乎我遇到了一个 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
}
(注意:出于演示目的,我从字段中删除了私有_。
若要避免基类错误地与子分支具有相等性的问题,可以添加对 runtimeType 的附加检查,如下所示。
bool operator ==(other) => other is Base
&& this.runtimeType == other.runtimeType
&& other.a == a
&& other.b == b;