| Author |
equals() vs inheritance
|
Gasan Guseynov
Ranch Hand
Joined: Jan 03, 2006
Posts: 67
|
|
Hi all,
Finally, got K&B Java 6 Study Guide. First glance at equals() explanation: same flaw as everywhere: instanceof check at first line. And they are telling us about equals() transitivity?! Is it only me who notice that this equals implementation isn't transitive when you have ancestors of this class?
|
 |
Martin Vanyavchich
Ranch Hand
Joined: Sep 16, 2008
Posts: 241
|
|
|
Why would't it be transitive if you have accessors?
|
SCJP 6, OCMJD 6, OCPJWSD 6
I no good English.
|
 |
Gasan Guseynov
Ranch Hand
Joined: Jan 03, 2006
Posts: 67
|
|
ancestors not accessors damn spellchecker. Here is what I'm talking about:
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
You are absolutely right that using instanceof often will break transitivity. That's why I only use instanceof in two cases:
1) the class is final
2) the equals method is final
In all other cases my equals methods look like this:
Because the classes are compared, a Foo object and a Bar object will never be equal to each other.
|
SCJP 1.4 - SCJP 6 - SCWCD 5
How To Ask Questions How To Answer Questions
|
 |
Matthew Brown
Bartender
Joined: Apr 06, 2010
Posts: 3791
|
|
|
Presumably there are some instances where this wouldn't be appropriate. An example is the contract for the equals() method of List objects - they should be considered equal if they contain equal objects in the same order, regardless of which implementation of List is being used.
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
True, but in those cases the Javadoc should mention that that is how the method should be implemented. Any other implementation will then be wrong.
Of course some classes in the API ignore this; a TreeSet with String.CASE_INSENSITIVE_ORDER as Comparator may be equal to a HashMap but not vice versa:
I believe this is mentioned in the TreeSet API.
|
 |
Seetharaman Venkatasamy
Ranch Hand
Joined: Jan 28, 2008
Posts: 5575
|
|
Rob Prime wrote:You are absolutely right that using instanceof often will break transitivity. That's why I only use instanceof in two cases:
1) the class is final
2) the equals method is final
I think you are worried about *symmetric* condition of equals . but again even getClass has disadvantage , It voilates Liskov substitution principle . because getClass pass the condition test, only if the two objects are belong to a same class.i.e, if you test whether some object of the subclass is equal to an object of the super class, it fails.
so, probably it is depends on your situation.
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
Seetharaman Venkatasamy wrote:I think you are worried about *symmetric* condition of equals .
You're right. I mixed the two up.
It voilates Liskov substitution principle . because getClass pass the condition test, only if the two objects are belong to a same class.i.e, if you test whether some object of the subclass is equal to an object of the super class, it fails.
But it doesn't necessarily mean that violates the LSP. The LSP isn't violated if I put a completely different object* into place. The behaviour of methods is then allowed to be different if this behaviour is dependent on the state of the object. If there is one method that is usually very dependent on the state it's the equals method.
* I can make a very strong case about a ColourPoint being quite different from a regular Point. After all, one has a colour, the other one doesn't. To me that makes them different and therefore non-equal. But I must admit that this discussion has the potential to turn into a VI vs Emacs discussion.
|
 |
Martin Vanyavchich
Ranch Hand
Joined: Sep 16, 2008
Posts: 241
|
|
In a way we need another method, something like equalsIgnoreInheritance(Object o) for everybody to be content
|
 |
Gasan Guseynov
Ranch Hand
Joined: Jan 03, 2006
Posts: 67
|
|
Rob Prime wrote:
But I must admit that this discussion has the potential to turn into a VI vs Emacs discussion.
Dear Rob,
I think the only correct point here will be to say that equals() implementations that we are tough from books are assuming that
1. there won't be ancestors (which is ridiculous, but whatever); 2. The object is to be put in a Hash table of any sort or will be heavily compared.
In other words, I'd like authors of these books to stop repeating the same #%#@ from one edition to another and turn on their brains. Meh.
|
 |
Gasan Guseynov
Ranch Hand
Joined: Jan 03, 2006
Posts: 67
|
|
|
Cause, well, I'm paying money not for a monkey training (which I can get online for free), but to improve my skills. That's all.
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32654
|
|
Yes, equalsIgnoreInheritance() could easily be implemented; it would not however have the symmetrical property of equals().
There are two good discussions I know about: one is in Joshua Bloch's Effective Java (you may be able to find the "sample" chapter for the 1st edition on the net still), the other will appear if you Google Angelika Langer Java equals.
|
 |
Rob Spoor
Sheriff
Joined: Oct 27, 2005
Posts: 19216
|
|
|
I agree that writers should mention both ways and then describe the pros and cons of both, and in the end let the programmer choose. Of all books I've read, only Effective Java mentions the Class comparison. Especially books for starters use instanceof blindly.
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32654
|
|
Gasan Gouseinov wrote: . . . this equals implementation isn't transitive when you have ancestors of this class?
They aren't called ancestors, but superclasses.
I may be mistaken, but I think, that is transitive when there are superclasses. It is when there are subclasses that transitivity fails.
|
 |
Gasan Guseynov
Ranch Hand
Joined: Jan 03, 2006
Posts: 67
|
|
Dear Ritchie,
You're right. I'm not a native speaker. I meant descendant, not ancestor. Sorry for inconvenience.
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32654
|
|
No problem
|
 |
Garrett Rowe
Ranch Hand
Joined: Jan 17, 2006
Posts: 1295
|
|
Campbell Ritchie wrote:Yes, equalsIgnoreInheritance() could easily be implemented; it would not however have the symmetrical property of equals().
There are two good discussions I know about: one is in Joshua Bloch's Effective Java (you may be able to find the "sample" chapter for the 1st edition on the net still), the other will appear if you Google Angelika Langer Java equals.
Here is one more from Odersky, Spoon, and Venners. Odersky uses some of the same techniques for the equals/== methods in the Scala standard library.
|
Some problems are so complex that you have to be highly intelligent and well informed just to be undecided about them. - Laurence J. Peter
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32654
|
|
|
That's another good description, thank you.
|
 |
 |
|
|
subject: equals() vs inheritance
|
|
|