Andreas Leitgeb wrote:
Then the instructor raised the point of deriving a "ColoredPoint"
and showed us the bad effect of the naive approach for overriding
equals (and hashCode()) in ColoredPoint.
This sort of situation should induce one to reassess the object
relations in an OO design.
In particular, ColoredPoint may not make much sense as a "kind of"
point, so much as a combination of a point and a color. Which means
instead of inheriting from Point (or Color) maybe it ought to be a
new
direct Object subclass that contains one of each.
Composition in place of inheritance is often what is needed in these
cases, rather than kludging the inherited methods to sort-of work.
Of course, it also depends on whether your design ever needs to use
ColoredPoints as generic points. Most likely, anywhere it seems to
do
so it really can be changed to operate on myColoredPoint.getPoint().
More generally, with value-type classes it's generally the case that
composited ones should be exactly that -- composited. Equality
comparisons between them rarely make sense, though there are
exceptions (integers are a subset of fractions, which are a subset
of
real numbers, which are a subset of complex numbers, is the textbook
example).
The other cases where cross-comparisons make much sense tend to be
collections that have the same semantics but different
implementations, like the various List implementations, as mentioned
elsewhere in this thread.
In any event, warty equals-and-hashCode implementations or thorny
problems trying to develop these parts of a class tend to indicate
the
need for a refactoring, and often for replacing inheritance with
composition somewhere up the class hierarchy from the problem class
or
classes.
excellent post, very thorough and well-reasoned. .