Re: How to Write an Equality Method in Java
Posted: Jun 4, 2009 11:12 AM
> > What exactly are we attempting to solve with this?
> > the most implementation-y form of inheritance to very
> > slightly reduce some minor code duplication? All so we
> > have Point3D extend Point2D or Circle extend Ellipse?
> The main point of the article is to try and spread the
> word more on the pitfalls of writing equals, and how to
> avoid them. Everything but the canEqual technique was
> already conventional wisdom, I think, but not necessarily
> widespread wisdom. So it doesn't hurt to remind folks.
> The point of canEqual is simply to show how to do
> something that I think was not conventional wisdom. The
> conventional wisdom, such as in Effective Java, is that
> this was not possible. I don't have a good use case off
> the top of my head, though.
I didn't mean to criticize the presentation itself, and I concur that further discussing this issue is a good thing in this instance.
However, I thought that the issue was that adding attributes to a concrete class is fundamentally at odds with the equivalence relation contracted by equals(). I'm surprised that there even is a workaround - I thought they were fundamentally incompatible!
In that sense, I definitely agree that the technique is interesting, and I didn't know about it, so I appreciate hearing about it.
> Somehow I didn't notice your comment about reducing code
> duplication. The problem wasn't code duplication, and I'm
> not sure which code you were thinking was being
> duplicated. The problem was that equals methods using
> instanceof without something like canEqual violate the
> superclass contract. This is apparently widespread in
> code. Regardless what LSP means, i do believe that in an
> OO program, subclasses should fulfill the superclass
It seems to me that the only reason to subclass Point2D into Point3D would be to reduce duplication (private final <numeric-type> x, y; getX(), getY(), constructor; equals and hashCode implementation, maybe part of the toString implementation). I've long doubted the maxim that OO-maps-the-real-world, and I don't think Point3D is-a Point2D anyway (a 2D point in 3D is a line!), so I wouldn't model it that way.
Specifically, I was referring to
this.x==that.x&&this.y==that.y: I don't think using a heavyweight technique like concrete implementation inheritance is called for simply to remove the duplication of those 15 tokens between Point2D and Point3D.