Point and ColorPoint
This lesson is based on the book "Effective
Java,
Programming Language Guide".
We consider the following class Point.
We want to add a new class ColorPoint, which makes it
possible to
create points with a color property.
Version 1
In this version, ColorPoint
does not override the method equals(Object). In that
case, it means that two points with different colors are nevertheless
equals if they have the same coordinates. This is probably not
what you want !
Version 2
In this version, ColorPoint
overrides equals. Now, two color points are equals iff they have the
same coordinates and the same colors.
Unfortunatly, this solution is wrong !
The equals(Object) method must respect the following
mathematical properties :
- reflexivity
o1.equals(o1) is always true.
- symmetry
o1.equals(o2) iff o2.equals(o1).
- transitivity
if o1.equals(o2) and o2.equals(o3) are true,
then o1.equals(o3) must be true.
But it is not the case with this implementation, as shown by the main
method of the class Test
:
public static void main(String[] args) {
Point p = new Point(10, 10);
ColorPoint cp = new ColorPoint(10, 10, Color.RED);
System.out.println(cp.equals(p));
System.out.println(p.equals(cp));
}
The result of the command
> java Test
is
false
true
Thus, the symmetry is not respected.
Version 3
In this version, we just modify the equals(Object) method
of ColorPoint.
If we compare a ColorPoint and a Point
which is not an instance of ColorPoint, we don't take
color into account. But this solution also is wrong, as shown by the
new main
method of the class Test
:
public static void main(String[] args) {
Point p = new Point(10, 10);
ColorPoint cp1 = new ColorPoint(10,10,Color.BLUE);
ColorPoint cp2 = new ColorPoint(10, 10, Color.RED);
System.out.println(cp1.equals(p));
System.out.println(p.equals(cp2));
System.out.println(cp1.equals(cp2));
}
The result of the command
> java Test
is
true
true
false
Thus the transitivity is
not respected.
Version 4
The previous versions have proved that an
instance of ColorPoint
cannot be a Point except if we accept that two instances
of ColorPoint
may be equals with different colors. Thus we propose a new version of ColorPoint
where we don't use inheritance, but only delegation. Note the method asPoint()
which makes it possible to have a "Point view" of an
instance of ColorPoint.
In this case, it is very easy to implement such a view because an
instance of Point is unmodifiable.
Version 5
We modify Point
in such a way that now, an instance of Point may be
modified, using the new method moveTo(int x, int y). We
modify ColorPoint
in the same way.
We also add a private method showMove() to ColorPoint
which prints a message when an instance of ColorPoint is
moved.
The Test
class shows that this method is called when using the method moveTo(int,
int) on an instance of ColorPoint. But, if we use
the method moveTo(int, int) on the Point
view, the instance of ColorPoint is moved, but the
message is not printed.
The result of the command
> java Test
is
moving to (20,20)
Current cp = (30,30) Color : java.awt.Color[r=0,g=0,b=255]
Version 6
To have a better control in ColorPoint
on the delegation to the instance of Point, we no longer
use a direct instance of Point, but an instance of a
subclass, called InternalClass. To access the private
method of ColoredPoint showMove(), this
subclass must be an internal class of ColoredPoint.
The class Point remains unchanged, and the class Test allows to
see that now, all the moves are printed.
The result of the command
> java Test
is
moving to (20,20)
moving to (30,30)