Behavior of opEquals
w0rp via Digitalmars-d
digitalmars-d at puremagic.com
Wed Sep 2 13:25:14 PDT 2015
On Wednesday, 2 September 2015 at 18:57:11 UTC, Jacob Carlborg
wrote:
> I encountered a problem in the implementation of
> std.xml.Document.opEquals (yes, I've reported an issue). The
> problem is demonstrated with this example:
>
> class Base
> {
> int a;
>
> override bool opEquals (Object o)
> {
> if (auto base = cast(Base) o)
> return base.a == a;
> else
> return false;
> }
> }
>
> class Foo : Base
> {
> int b;
>
> override bool opEquals (Object o)
> {
> if (auto foo = cast(Foo) o)
> return super == cast(Base) foo && foo.b == b;
> else
> return false;
> }
> }
>
> void main()
> {
> auto f1 = new Foo;
> auto f2 = new Foo;
> assert(f1 == f2);
> }
>
> This code will result in an infinite recursion. I think the
> problem is in the super call, due to == being rewritten to call
> object.opEquals. The implementation of object.opEquals will
> call opEquals on the actual instances. The call will be
> dynamically resolved and end up calling Foo.opEquals instead of
> Base.opEquals.
>
> Is this really good behavior, something a developer would
> expect? I mean, in every other case calling super.someMethod
> will actually call the method in the base class.
>
> In this case the solution/workaround is to explicitly call
> super.opEquals, but that will miss some optimizations
> implemented in object.opEquals.
Yeah, I would just call super.opEquals, like so.
class Base {
int a;
override bool opEquals(Object o) {
if (auto other = cast(Base) o)
return a == other.a;
return false;
}
}
class Foo : Base {
int b;
override bool opEquals(Object o) {
if (!super.opEquals(o))
return false;
if (auto other = cast(Foo) o)
return b == other.b;
return false;
}
}
void main()
{
auto f1 = new Foo;
auto f2 = new Foo;
assert(f1 == f2);
}
If some optimisations are missed by structuring the methods in
this way, then maybe that's something the compiler should be
programmed to handle.
More information about the Digitalmars-d
mailing list