opEquals and the Non-Virtual Interface idiom

downs default_357-line at yahoo.de
Sun Sep 27 13:17:55 PDT 2009


Jeremie Pelletier wrote:
> grauzone wrote:
>> Andrei Alexandrescu wrote:
>>> Here's an article about the perils of equals in Java (opEquals in D):
>>>
>>> http://www.ddj.com/article/printableArticle.jhtml;jsessionid=GFKUCQH5S4IHNQE1GHOSKHWATMY32JVN?articleID=184405053&dept_url=/java/
>>>
>>>
>>> It turns out this is a great example for NVI. In D, we could and should
>>> do the following:
>>>
>>> class Object {
>>>     // Implement this
>>>     private bool opEqualsImpl(Object rhs) {
>>>         return false;
>>>     }
>>>     // Use this
>>>     final bool opEquals(Object rhs) {
>>>         if (this is rhs) return true;
>>>         if (this is null || rhs is null) return false;
>>>         return opEqualsImpl(rhs) && rhs.opEqualsImpl(this);
>>>     }
>>> }
>>>
>>> I took advantage of the fact that in a final function this may be null
>>> without an access violation. The implementation above ensures symmetry
>>> of equality and has each class implement a simpler primitive.
>>>
>>> What do you think?
>>
>> Eh, now after all this discussion, we're going to allow even "this" to
>> be null? That seems like a backstep...
> 
> How is it a backstep? It's perfectly valid behavior.
> 
> Object foo;
> foo.opEquals(foo);
> 

What is the semantics of that call?

"Is something undefined equal to something undefined"? I'm not sure why that should be considered valid behavior, given that it's unanswerable.

> The call itself will *always* succeed, its when 'this' gets referenced
> in opEquals that the code will crash.

Or when a contract is run. Or when an inherited contract is run. Or when the method attempts to lock the synchronization object.

> 
>> Implementing opEquals as a global/static function, that calls the
>> actual Object.opEquals virtual method would be so much more straight
>> forward.
> 
> I agree, I prefer methods to end with Impl to stay hidden instead of
> being the ones to override.
> 
>> PS: I agree about the NVI thing. If you'd go to extend the language
>> for "NVI", couldn't we just introduce a second type of virtual
>> function that works this way:
>> 1. the super class' implementation is _always_ called first
>> 2. the super class function can decide to "call down" to the sub
>> class' implementation of the same method
>> => no extra do<something> method needed, and the code is (possibly)
>> clearer.
>>
>>> Andrei
> 
> I don't know how useful that would be, when you override a method you
> usually want to call the super method somewhere in the new
> implementation, not always at the beginning.



More information about the Digitalmars-d mailing list