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)