A fresh look at comparisons
Janice Caron
caron800 at googlemail.com
Mon Apr 14 23:49:21 PDT 2008
On 15/04/2008, Scott S. McCoy <tag at cpan.org> wrote:
> But you're making assumptions about the application's definition of
> equality.
I was, and I got that part wrong, so I retract that part of the idea. See below.
> See, that's the point of having opEquals overloadable:
I get that now. So what you're basically saying is that
is(this == c)
isn't enough, because it makes the presumption that typeof(c) /must/
be the same as typeof(this). Whereas, we really need to allow the
programmer to overload for different types.
Still, only a minor change to my proposal would be needed to
accomodate this. We only need to allow the test to be overloaded, so:
is(this == c) /* standard test */
is(this == C c) /* overload for type C */
> Can you say definitively and for certain that in all
> environments in all programs ever written in D, that an object of type A
> and an object of type B will never be equal even though they have no
> common ancestor?
No, so obviously you're right, and we would need to make it
overloadable, as per the above example.
> And also, we cannot say that for instance, if you have types B and C
> which are both descendants of type A, that you will want B to be equal
> to C if A.opEquals() returns true for the two instances.
You're right, and that's one thing I don't like about opEquals, and
which is(==) would solve. So, under the revised proposal:
class A
{
is(this == c) {...}
}
class B : A {}
class C : A {}
B b;
C c;
if (b == c) ...
This test would now have to return false always, because the new rules
must compare B with B, or C with C, and must /not/ cast b and c to
their common type. Under the new rules, to compare B with C, the
programmer would now have to write
class B : A
{
is(this == C c) {...}
}
class C : A
{
is(this == B b) {...}
}
I think that covers all the edge cases that people have pointed out.
With that adjustment, the scheme, I think, now works a treat.
As you know, in existing D, opEquals(), at least for classes, is
defined to take an Object parameter, not a C parameter, so even
ignoring the inheritance rules, allowing opEquals to compare against
multiple types is tricky. You end up writing code like
int opEquals(Object o)
{
A a = cast(A)o;
B b = cast(B)o;
C c = cast(C)o;
if (c !is null)
{
...
}
else if (b !is null)
{
...
}
else if (a !is null)
{
...
}
}
which is not ideal
More information about the Digitalmars-d
mailing list