Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion .Equals()

Received: by 10.35.127.7 with SMTP id e7mr1864278pyn.1193681203118;
        Mon, 29 Oct 2007 11:06:43 -0700 (PDT)
Received: by 22g2000hsm.googlegroups.com with HTTP;
	Mon, 29 Oct 2007 18:06:42 +0000 (UTC)
X-IP: 83.141.125.125
From:  Martin OConnor <marti...@gmail.com>
To:  The Java Posse <javaposse@googlegroups.com>
Subject: Re: .Equals()
Date: Mon, 29 Oct 2007 11:06:42 -0700
Message-ID: <1193681202.011580.259700@22g2000hsm.googlegroups.com>
In-Reply-To: <4726097D.6090408@SmokejumperIT.com>
References: <472263E3.4070001@SmokejumperIT.com>
   <1193674696.705296.90230@y42g2000hsy.googlegroups.com>
   <4726097D.6090408@SmokejumperIT.com>
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.8) Gecko/20071008 Firefox/2.0.0.8,gzip(gfe),gzip(gfe)
MIME-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"

Why are you making things more complicated by having ThreeDeePoint
extend TwoDeePoint? Its like trying to force a square peg in a round
hole! A straight comparison between a ThreeDeePoint and a TwoDeePoint
should *ALWAYS* return false. Both ThreeDeePoint and TwoDeePoint
should extend Object (not explicitly of course), and if for instance
you want to compare a TwoDeePoint to a ThreeDeePoint in a certain
space, then translate the TwoDeePoint into the appropriate
ThreeDeePoint space and compare the output from the translation for
equality.

On Oct 29, 4:25 pm, Robert Fischer <Robert.Fisc...@SmokejumperIT.com>
wrote:
> Your first paragraph gets at exactly the issue with having an instance-based #equals/#compareTo.
> The delegating-equals approach is interesting.  I tried to dig at that spot before, but never got the implementation quite right.  I'm going to think on that some more.
> ~~ Robert.
> Kevin Wong wrote:To clarify, what exactly is the desired behaviour of the equals implementation here? Assume TwoDeePoint p1 = (1,2) and ThreeDeePoint pz = (1,2,z). Do you want p1.equals(pz) to return true? This would be wrong because there would be no way to satisfy transitivity. Assume ThreeDeePoint p2 = (1,2,3) and ThreeDeePoint p3 = (1,2,4). p1.equals(p2) would return true, p1.equals(p3) would return true, but p2.equals(p3) would return false; transitivity broken. This is unless you want to handle the z=0 case explicitly, which would be another story. I think the more common case involves subclasses the introduce fields that do not have implied default values in the superclass (one could arge that TwoDeePoint's implied value for z is 0). Perhaps it would be more productive to discuss the Point/ColorPoint example in Josh Block's Effective Java Programming Language Guide (Addison-Wesley, 2001). In that case, it would be stretch to assert that a ColorPoint's equality with a Point should be dependent on its color being set to null (such as the z=0 case). In regards to a p1.equals(pz) == false solution for the TwoDeePoint/ ThreeDeePoint problem, consider this (based onhttp://www.ddj.com/java/184405053):public class TwoDeePoint { public int x = 0; public int y = 0; protected boolean blindlyEquals(Object o) { if (!(o instanceof TwoDeePoint)) return false; TwoDeePoint p = (TwoDeePoint)o; return (p.x == this.x && p.y == this.y); } public boolean equals(Object o) { if (!(o instanceof TwoDeePoint)) return false; TwoDeePoint p = (TwoDeePoint)o; return (this.blindlyEquals(p) && p.blindlyEquals(this)); } } public class ThreeDeePoint extends TwoDeePoint { public int z = 0; protected boolean blindlyEquals(Object o) { if (!(o instanceof ThreeDeePoint)) return false; ThreeDeePoint p = (ThreeDeePoint)o; return (super.blindlyEquals(p) && p.z == this.z); } } import static org.junit.Assert.*; public class Test { @org.junit.Test public void testEquals() throws Throwable { final TwoDeePoint a = new TwoDeePoint(); a.x = 1; a.y = 2; final ThreeDeePoint b = new ThreeDeePoint(); b.x = a.x; b.y = a.y; b.z = 3; final ThreeDeePoint c = new ThreeDeePoint(); c.x = a.x; c.y = a.y; c.z = 3; final ThreeDeePoint d = new ThreeDeePoint(); d.x = a.x; d.y = a.y; d.z = 4; assertFalse(a.equals(b)); assertEquals(a.equals(b), b.equals(a)); assertTrue(b.equals(c)); assertFalse(b.equals(d)); } } Overriding blindlyEquals frees subclasses from the constraint of symmetry, as that is provided by the inherited implementation of equals. On Oct 26, 6:02 pm, Robert Fischer<Robert.Fisc...@SmokejumperIT.com>wrote:Hey there. Jumping on because 1) the list was recommended to me, and 2) your conversation on #equals seemed good. I've got a few posts on #equals on my blog, which I linked to off of this post:http://enfranchisedmind.com/blog/archive/2007/10/26/417I'm yet to encounter a general inheritance-safe solution for equals beyond externalizing the equals/compareTo implementation. Check out the TwoDeePoint and ThreeDeePoint examples in my blog: if you've got a good solution for that, you'll be my hero. The best suggestion I have is that if the classes of two objects aren't equal, then they shouldn't be equal. That's the safest way to implement a built-in version of #equals/#compraeTo. ~~ Robert.