Java Reference
In-Depth Information
not only if the variable refers to that type, but also if it refers to any of its subclasses.
Consider the following test in the equals method of the Point class:
if (o instanceof Point) {
...
}
The test will evaluate to true if o refers to a Point object or a Point3D object.
The instanceof operator is like an is-a test, asking whether the variable refers to
any type that can fill the role of a Point . By contrast, Point3D 's equals method
tests whether the parameter is an instance of Point3D and rejects it if it is not. A
Point cannot fill the role of a Point3D (not every Point is a Point3D ), so the
method will return false if the parameter is of type Point .
Consequently, the equals behavior is not symmetric when it is used with a mixture
of Point and Point3D objects. The following client code demonstrates the problem:
Point p = new Point(12, 7);
Point3D p3d = new Point3D(12, 7, 11);
System.out.println("p.equals(p3d) is " + p.equals(p3d));
System.out.println("p3d.equals(p) is " + p3d.equals(p));
The code produces the output that follows. The first test returns true because a
Point can accept a Point3D as the parameter to equals , but the second test returns
false because a Point3D cannot accept a Point as its parameter to equals :
p.equals(p3d) is true
p3d.equals(p) is false
This is a problem, because the contract of the equals method requires it to be a
symmetric operation. You'd encounter other problems if you added more behavior to
Point3D , such as a setLocation or distance method.
Proper object-oriented design would not allow Point3D to extend Point , because
any code that asks for a Point object should be able to work correctly with a
Point3D object as well. We call this principle substitutability. (It is also sometimes
called the Liskov substitution principle, in honor of the Turing Award-winning author
of a 1993 paper describing the idea.)
Substitutability
The ability of an object of a subclass to be used successfully anywhere an
object of the superclass is expected.
Fundamentally, a Point3D isn't the same thing as a Point , so an is-a relationship
with inheritance is the wrong choice. In this case, you're better off writing Point3D
from scratch and avoiding these thorny issues.
 
Search WWH ::




Custom Search