The Artima Developer Community
Sponsored Link

Weblogs Forum
Some Objects are More Equal Than Others

28 replies on 2 pages. Most recent reply: Jan 25, 2007 9:03 AM by antonio lucca

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 28 replies on 2 pages [ « | 1 2 ]
Ken Arnold

Posts: 27
Nickname: arnold
Registered: Apr, 2003

Re: Some Objects are More Equal Than Others Posted: May 15, 2003 4:47 AM
Reply to this message Reply
Advertisement
Okay, I should never, ever, post something when I'm jetlagged without reading it three times instead of twice. I read sloppily, and so made a stupid comment. Sigh.

I've seem people claim you should use a comparison using Foo.class, but Cay is not saying that. Obviously testing class equality is not the same -- that would be quite sufficient for the case which I'm concerned about.

This would be a non-issue for me if I didn't generally agree with Josh on this subject. But I've obviously blown my cred for this thread of discussion, so I will just slink off and pretend I wasn't here...

Ken

Channing Walton

Posts: 32
Nickname: channing
Registered: May, 2003

Re: Some Objects are More Equal Than Others Posted: May 15, 2003 4:55 AM
Reply to this message Reply
How does one deal with classloader issues? Should two objects with identical data be equal if they've been loaded with different classloaders?

Channing

Robb Nebbe

Posts: 3
Nickname: robb
Registered: May, 2003

Re: Some Objects are More Equal Than Others Posted: May 15, 2003 7:10 AM
Reply to this message Reply
I agree with your point and here is how I think of the problem.

If you organize your classes into a hierarchy where all the leaf classes are concrete and all the upper-level classes are abstract then it is easier to see that every class has its own notion of equality. In the concrete classes the concept of equality is as you suggest while in the abstract classes it just compares what is common to all the subclasses.

When a concrete class inherits from another concrete class the problem is that the parent class plays two roles; it describes what the two classes have in common while at the same time serving as a complete description for one of the classes. There is a notion of equality associated with both of these roles and this is, in my opinion, the source of confusion.

When I read source code the fact that a concrete class inherits from another concrete class is a red flag for this kind of confusion.

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

Bad Policy - Think again Posted: May 16, 2003 1:43 PM
Reply to this message Reply
Your policy is naive and produces buggy behavior. Following this poorly considered policy has already produced inconsistencies in the java.lang.* classes.

Example:

int anInt = 5;
long aLong = 5;

if(anInt == aLong) // this works.

But then the designers of java.lang.* followed your advice:

Integer anInteger = new Integer(5);
Long aLong = new Long(5);

if(anInteger.equals(aLong)) // returns false - so 5!=5 !?!?

This result is wholly unexpected by the reasonable developer. Furthermore, its wrong behavior that has bedevlied many a user of reflection based libraries.

This includes my own qualifier library, - a library that uses the interpreter pattern to store match patterns on arbitrary java object clusters. It uses external comparators simply because you can't trust the implementation of equals() in the java.lang.Number cluster.

So this is just plain bad advice and shows a simplistic mind set.

Todd Blanchard

Brett Neumeier

Posts: 1
Nickname: random
Registered: May, 2003

Re: Some Objects are More Equal Than Others Posted: May 16, 2003 6:21 PM
Reply to this message Reply
I'm glad to see someone else writing about this -- this topic seems to come up a lot!

In case anyone's interested, Dr Mark Davis (co-founder of the Unicode consortium, among other things) wrote about this years ago in his Durable Java column:

http://www.macchiato.com/columns/Durable5.html

While I was finding that link above, I noticed that he recommends that people look at this article for mixed-type comparisons:

http://www.cuj.com/java/articles/a22/a22.htm

Cheers,

Brett Neumeier

Cay Horstmann

Posts: 13
Nickname: cay
Registered: Apr, 2003

Re: Bad Policy - Think again Posted: Jun 9, 2003 3:44 PM
Reply to this message Reply
Hi Todd!

Thanks for an interesting example.

Note that in the standard library,

new Integer(5).equals(new Long(5))

does return false. That's how Arthur van Hoff implemented it circa 1995.

Is that a bad policy? Was Arthur naive? I don't think so.

Suppose he had made it possible to compare Integer and Long values. Then JDK 1.1 added BigInteger. That would have broken the existing comparison scheme.

Cheers,

Cay

Todd Blanchard

Posts: 316
Nickname: tblanchard
Registered: May, 2003

Re: Bad Policy - Think again Posted: Jun 21, 2003 9:42 PM
Reply to this message Reply
Arthur van Hoff is wrong I think. Don't you?

I mean, if Integer and Long are meant to be Object standins for int and long (and that appears to be the case), then why does comparing an int and long obey different rules than comparing Integer and Long? And YTF shouldn't 5 = 5, regardless of how the 5 happens to be stored in memory?

No good reason in my book and I've been bitten by this many times when using generic reflection style invocations to perform queries on collections of objects. The only rational characterization of this behavior is that it is a bug.

"Suppose he had made it possible to compare Integer and Long values. Then JDK 1.1 added BigInteger. That would have broken the existing comparison scheme. "

I don't follow this "reasoning" at all. Yes, extending the set of value classes would necessitate extending the original scheme. My response is "So?"

If java had decent numerics at the beginning we wouldn't be having this conversation.

Anyhow, the sensible technique for this is to implement double dispatch (visitor pattern to you C++ and J-heads).

I'll note that Smalltalk solved this issue over 20 years ago with arbitrary precision math and I remain disgusted that we are still dealing with trivial issues like this in our programming languages.

Ravi Venkataraman

Posts: 80
Nickname: raviv
Registered: Sep, 2004

Re: Bad Policy - Think again Posted: Dec 8, 2004 9:42 AM
Reply to this message Reply
Todd said,
Example:

int anInt = 5;
long aLong = 5;


This happens because Java (and many languages) distinguish between short, int, long, BigInteger, etc.

OO is supposed to be closer to the problem domain than other previous paradigms such as Structured programming, etc.

How often have you thought like this: I want to find the factorial of (int) 100? Or, I'd like to have a salary of (int) 1,000,000 per year.

Yet this is how many programmers write their code! Why can't the JVM decide at runtime whether it is an int, long or BigInteger?

The very fact that int, long and BigInteger (and their decimal counterparts) exist suggest that there is room for improvement in C based languages (C, C++, C# and Java).

When Java touted OS independence at the very beginning, one of the key selling points was that an int would always be the same 16 bits (or 32 bits, or whatever) in every machine it ran on.

A side effect of these decisions, along with the decision to differentiate between primitives and Objects, is that code becomes extremely bloated. And you get unexpected results.

J. R.

Posts: 2
Nickname: syrion
Registered: Mar, 2005

Re: Some Objects are More Equal Than Others Posted: Mar 31, 2005 7:56 AM
Reply to this message Reply
Objects of different *classes can* be equal. These are "true" for example:
new HashSet().equals(new TreeSet()))
new LinkedList().equals(new ArrayList()))
new HashMap().equals(new TreeMap())


That's exactly wath Cay :
You should almost always test for getClass() != other.getClass() in an equals method
There is a small number of cases where instanceof makes sense, namely if
a superclass has fixed the semantics for equals
the state of various subclasses differ in inessential ways from the state of the superclass
and the subclasses can add value by redefining equals to be more efficient
This is the case in the java.util.Collection hierarchy.


Your example with Sets, Lists and Maps falls into the case you shoud use instanceof ! So it is not an example that invalidates the "!getClass()==other.getClass()" theory.

"instanceof" and "getClass()" supporters both have good arguments, but thay all failled to prouve their own theory was the only one good theory. All couner-exemple they gave to invalidate opponent's theory were specifics cases.

And more, many exemples shows that Liskov substitution cannot always be satisfied. So respect it only if you don't get unhexpected results or behaviour ! Nobody prouved Liskov was absolutely right, liskov principles are only postulates. What is stronger : equals logic, or Likov priinciple ? Because every Mathematician could be shocked by the fact that a.equals(b) and !b.equals(a). Indeed, if B extends A, B instanceof A is true, but A instanceof B is false.

So what should I do ? I should NEVER use an automatic equals() implementation. I should always keep in mind advantages and drawbacks of both implementations. The author of the article said it : if you give some semantic to equals(), you may want to use instanceof. In some cases you should use instanceof. Perhaps in a lot of cases. But in a lot of cases too, it will be bad to not respect teh equals symetry.

In conclusion, we have to know the issue with equals(), choose the suitable implementation for our case, then document it. And never arbitrarily decide that one is better than the other. Remember nobody proved that an implementation is always better than the other, but everybody experienced strange behaviour or false results with both[i/] implementations !

John Doe

Posts: 5
Nickname: mrpantsuit
Registered: Oct, 2006

Re: Some Objects are More Equal Than Others Posted: Jan 3, 2007 2:21 PM
Reply to this message Reply
I think you have that backwards. It is the use of getClass in equals() that violates the Liskov substitution principle.

The principle states: Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T. If q() is equals(), and we use getClass in its implementation, then equals(y) will never be true.

John Doe

Posts: 5
Nickname: mrpantsuit
Registered: Oct, 2006

Re: Some Objects are More Equal Than Others Posted: Jan 3, 2007 2:33 PM
Reply to this message Reply
Sorry, my post above was in response to Johan H's post on page 1. (I thought this forum app would somehow indicate a reply's target. Silly me.)

Also, has anyone seen the "blindlyEquals" solution presented here: http://www.ddj.com/dept/java/184405053? Is this not a complete solution?

antonio lucca

Posts: 3
Nickname: tonyxzt
Registered: Jan, 2007

Re: Some Objects are More Equal Than Others Posted: Jan 9, 2007 6:39 AM
Reply to this message Reply
Hello, I'm new to this site.

I wrote now a post in my new blog here http://tonyxzt.blogspot.com/2007/01/liskov-substitution-principle-in-java.html
about liskov substitution principle and equals implementation in a way to preserve both lsp and equals contract (transitivity and simmetry).

I know that there can be no simmetry and/or transitivity when compare a class with a subclass, using instanceof, but I think it can be fixed in some way I implemented in my example code, particularly using this strategy:
The equals implemented by a class checks if the argument is an instance of any subclass, and if so, it should delegate to the subclass the equals control.
(this is not all the strategy, but just a part of it).

There is source code available with different packages that shows step by step this, with sources and junit tests, there.
http://code.google.com/p/sampleliskov/

(I've not provided an ant build script until now)

Thanks.

Tonino.

Joel Neely

Posts: 10
Nickname: joelneely
Registered: Mar, 2003

Re: Some Objects are More Equal Than Others Posted: Jan 16, 2007 4:37 PM
Reply to this message Reply
I am beginning to suspect that our problem is with the assumption that there's only one "equals". Let me imagine that "a equals b" means that they are interchangable for some set of purposes. Does that mean that they are interchangeable for all purposes?

For a concrete example, suppose I have a Rectangle class (with height and width) and a Square class (with only edge). Are there purposes for which new Rectangle(2.0, 2.0) could be considered equal to new Square(2.0)?

If so, would it still make sense to stipulate that equals(...) really should be restricted to mean "objects of equal classes with equivalent state" and define a separate boolean equivalent(Rectangle r, Square s) method somewhere external to both?

Or is "equal to for the purposes of this domain" worthy of being institutionalized in equals(...)?

antonio lucca

Posts: 3
Nickname: tonyxzt
Registered: Jan, 2007

Re: Some Objects are More Equal Than Others Posted: Jan 25, 2007 9:03 AM
Reply to this message Reply
> I am beginning to suspect that our problem is with the
> assumption that there's only one "equals". [...]
>


I think a part of our problems is what is a "sound" implementation of equals in terms of object oriented approach, expecially in relation to classes/subclasses hierarchy.

> Let me imagine
> that "a equals b" means that they are interchangable for
> some set of purposes. Does that mean that they are
> interchangeable for all purposes?


I think that if for any reason we consider better allowing classes/subclasses comparison, then we have to deal with the topic of this post (getClass vs instanceof).

T.

Flat View: This topic has 28 replies on 2 pages [ « | 1  2 ]
Topic: Some Objects are More Equal Than Others Previous Topic   Next Topic Topic: Come join me at PyCon 2007!

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use