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.