Java Reference
In-Depth Information
A Subclass Object Contains the Instance Variables of All of Its Superclasses
When you create a BasePlusCommissionEmployee object, it contains all instance variables
declared in the class hierarchy to that point—that is, those from classes Object (which
does not have instance variables), CommissionEmployee and BasePlusCommissionEmploy-
ee . Class BasePlusCommissionEmployee does not inherit CommissionEmployee 's five-ar-
gument constructor, but explicitly invokes it (lines 14-15) to initialize the instance variables
that BasePlusCommissionEmployee inherited from CommissionEmployee . Similarly, Com-
missionEmployee 's constructor implicitly calls class Object 's constructor. BasePlusCom-
missionEmployee 's constructor must explicitly call CommissionEmployee 's constructor
because CommissionEmployee does not have a no-argument constructor that could be in-
voked implicitly.
Testing Class BasePlusCommissionEmployee
The BasePlusCommissionEmployeeTest class for this example is identical to that of
Fig. 9.7 and produces the same output, so we do not show it here. Although the version of
class BasePlusCommissionEmployee in Fig. 9.6 does not use inheritance and the version in
Fig. 9.9 does, both classes provide the same functionality. The source code in Fig. 9.9 (59
lines) is considerably shorter than that in Fig. 9.6 (127 lines), because most of the class's
functionality is now inherited from CommissionEmployee —there's now only one copy of
the CommissionEmployee functionality. This makes the code easier to maintain, modify
and debug, because the code related to a CommissionEmployee exists only in that class.
Notes on Using protected Instance Variables
In this example, we declared superclass instance variables as protected so that subclasses
could access them. Inheriting protected instance variables enables direct access to the
variables by subclasses. In most cases, however, it's better to use private instance variables
to encourage proper software engineering. Your code will be easier to maintain, modify
and debug.
Using protected instance variables creates several potential problems. First, the sub-
class object can set an inherited variable's value directly without using a set method. There-
fore, a subclass object can assign an invalid value to the variable, possibly leaving the object
in an inconsistent state. For example, if we were to declare CommissionEmployee 's instance
variable grossSales as protected , a subclass object (e.g., BasePlusCommissionEmployee )
could then assign a negative value to grossSales . Another problem with using protected
instance variables is that subclass methods are more likely to be written so that they depend
on the superclass's data implementation. In practice, subclasses should depend only on the
superclass services (i.e., non- private methods) and not on the superclass data implemen-
tation. With protected instance variables in the superclass, we may need to modify all the
subclasses of the superclass if the superclass implementation changes. For example, if for
some reason we were to change the names of instance variables firstName and lastName
to first and last , then we would have to do so for all occurrences in which a subclass
directly references superclass instance variables firstName and lastName . Such a class is
said to be fragile or brittle , because a small change in the superclass can “break” subclass
implementation. You should be able to change the superclass implementation while still
providing the same services to the subclasses. Of course, if the superclass services change,
we must reimplement our subclasses. A third problem is that a class's protected members
 
Search WWH ::




Custom Search