Win a copy of Design for the Mind this week in the Design forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

equals() vs inheritance

 
Gasan Guseynov
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 241
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Why would't it be transitive if you have accessors?
 
Gasan Guseynov
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
ancestors not accessors damn spellchecker. Here is what I'm talking about:

 
Rob Spoor
Sheriff
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Matthew Brown
Bartender
Posts: 4566
8
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 5575
Eclipse IDE Java Windows XP
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 241
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In a way we need another method, something like equalsIgnoreInheritance(Object o) for everybody to be content
 
Gasan Guseynov
Ranch Hand
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 20511
54
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 67
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dear Ritchie,

You're right. I'm not a native speaker. I meant descendant, not ancestor. Sorry for inconvenience.
 
Campbell Ritchie
Sheriff
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No problem
 
Garrett Rowe
Ranch Hand
Posts: 1296
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Campbell Ritchie
Sheriff
Posts: 48652
56
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's another good description, thank you.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic