A Fresh Look at Comparisons, Take 2

Steven Schveighoffer schveiguy at yahoo.com
Fri Apr 18 11:16:13 PDT 2008


"Yigal Chripun" wrote
> Steven Schveighoffer wrote:
>> Huh?  I think maybe you meant C to inherit from B?  If so I see what you 
>> are
>> trying to explain :)
>>
>> I don't really agree that opEquals or opCmp should not be inherited.  I
>> think normal inheritance the way it is now is just fine.
>>
> as Janice showed and I completely agree with her, this is a bad default.
> We are talking about the D default behavior here and it can be
> overridden. The programmer can define an opCmp that is not explicit and
> than all derived classes will inherit that opCmp as well, so your
> desired behavior is still available, it's just not the default anymore.

I think the whole goal of this exercise is to avoid having to take 'Object' 
as the parameter to opCmp and opEquals.

Why can't one just provide opCmp(MySpecificClass) as an overload to opCmp? 
If the compiler sees it at compile time, it calls the more specific one.

Maybe in that case, the default opCmp in Object can do the casting for you:

int opCmp(Object o)
{
   /* search through vtable for opCmp that takes most derived compatible 
type, call it with o*/
   /* if no such function exists, throw exception */
}

If you want to define a more efficient opCmp, then override opCmp(Object o) 
that will call just the functions you want.  It's not any different than 
today.

I don't know how one would write this in D directly, but it could 
theoretically be done.

Adding a new 'explicit' keyword may also solve this problem, but it also 
appears to introduce a lot of other problems that I don't think we want to 
have.

>> You need to have opEquals in Object in order to support hashing.
>>
> I'm not sure I fully understand you on this. the suggestion states that
> unless opEquals is defined, the compiler defaults to identity
> comparison.  This is equivalent to having an opEquals in Object that
> does the same thing (which is the current implementation, I think). I
> don't care if it's implemented inside the compiler, or via opEquals in
> Object, what's important is the semantics. i.e. unless there's a user
> defined opCmp for a class, (a == b) will be true iff (a is b) is true [
> for two instances a and b of that class].

"unless opEquals is defined, the compiler defaults to identity comparison."

This is the current implementation.  I'm not sure why we need special 
handling of it.

>> The default opCmp should be redefined to throw an exception.  An 
>> alternative
>> is that opCmp is defined in an interface.  Or you could do both.  The
>> rationale is that opCmp doesn't have a default.  Some objects just cannot 
>> be
>> expected to have a well-defined order.
>>
>> -Steve
>>
>>
>>
> since D is relatively a new language, we can benefit by learning from
> previous design errors in similar languages. Java implements that idea
> of a method in Object that throw by default and that proved to be a very
> fragile design. Object should provide only the methods that all objects
> contain, and since not all classes are fully ordered, opCmp should not
> be in Object.
> I agree with you that providing a "Comparable" interface is a good
> design. If D was only OOP like java, than this would have been my
> favorite solution. indeed, Java contains such an interface and you are
> expected to implement it if your class is comparable. if i remember
> correctly, there are two interfaces in Java which facilitate the subtle
> difference between an opEquals and opCmp comparison.
> as Janice said, this interface is not strictly necessary with her
> proposal, however such an interface can help document the fact that a
> class is comparable, so it still could be added.

My preference is the interface.  But I'm willing to accept an 'exception 
throwing' default (or the 'find the right overload' default as defined 
above) if that is what Walter wants.  This is all I'm saying.

-Steve 





More information about the Digitalmars-d mailing list