THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

creates a new kind of object that "is a" kind of the original class. The IsA relationship is quite different from a
HasA relationship, in which one object uses another object to store state or do workit "has a" reference to that
other object.


Let's look at an example. Consider a Point class that represents a point in two-dimensional space by an (x,
y) pair. You might extend Point to create, say, a Pixel class to represent a colored point on a screen. A
Pixel IsA Point: anything that is true of a simple Point would also be true of a Pixel. The Pixel
class might add mechanisms to represent the color of the pixel or a reference to an object that represents the
screen on which the pixel is drawn. As a point in a two-dimensional space (the plane of a display) with an
extension to the contract (it has color and a screen), a Pixel IsA Point.


On the other hand, a circle is not a point. Although a circle can be described by a point and a radius, a point
has uses that no circle would have. For example, if you had a method to place the center of a rectangle at a
particular point, would it really make sense to pass in a circle? A circle HasA center that IsA point, but a
circle IsNotA point with a radius, and therefore should not be a subclass of Point.


There are times when the correct choice is not obvious and for which different choices will be correct
depending on the application. In the end, applications must run and make sense.


Getting IsA versus HasA relationships correct is both subtle and potentially critical. For example, one obvious
and common way to design an employee database using object-oriented tools is to use an Employee class
that has the properties all persons share (such as name and employee number) and extend it to classes for
particular kinds of employees, such as Manager, Engineer, and FileClerk.


This design fails in real-world situations, in which one person operates simultaneously in more than one role.
For example, an engineer might be an acting manager in a group and must now appear in two guises. As
another example, a teaching assistant is often both a student and a staff member at a university.


A more flexible design would create a Role class and extend it to create classes for roles such as Manager.
You would then change the design of the Employee class to have a set of Role objects. A person could
now be associated with an ever-changing set of roles in the organization. We have changed from saying that a
manager IsAn employee to saying that manager IsA role, and that an employee can HaveA manager's role as
well as other roles.


If the wrong initial choice is made, changing deployed systems will be hard because changes could require
major alterations in code. For example, methods in the first employee database design would no doubt rely on
the fact that a Manager object could be used as an Employee. This would no longer be true if we had to
change to the role-based design, and all the original code would break.


3.11. Designing a Class to Be Extended


The Attr class is an example of a well-designed classit follows the design principles that you learned in
Chapter 2. The fields of the class are private and accessible only through accessor methods, thereby
protecting them from modifications that violate the class's contract. The Attr class presents a clean interface
to users of the class and at the same time decouples itself from those classes to allow its own implementation
to change in the future.


Given that ColorAttr extends Attr, should we have designed Attr differently to make it more suitable
for extension? Should the name and value fields have been protected, instead of private, so that a
subclass could access them directly? Such decisions require careful thought and consideration of both the
benefits and consequences. Making the Attr fields protected would not benefit a subclass because all of the

Free download pdf