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