We now discuss the second part of our introduction to inheritance by declaring and testing (a completely new and independent) class BasePlusCommissionEmployee
(Fig. G.6), which contains a first name, last name, social security number, gross sales amount, commission rate and base salary. Class BasePlusCommissionEmployee
’s public
services include a BasePlusCommissionEmployee
constructor (lines 15–25) and methods earnings
(lines 112–115) and toString
(lines 118–127). Lines 28–109 declare public
get and set methods for the class’s private
instance variables (declared in lines 7–12) firstName
, lastName
, socialSecurityNumber
, grossSales
, commissionRate
and baseSalary
. These variables and methods encapsulate all the necessary features of a base-salaried commission employee. Note the similarity between this class and class CommissionEmployee
(Fig. G.4)—in this example, we’ll not yet exploit that similarity.
1 // Fig. G.6: BasePlusCommissionEmployee.java
2 // BasePlusCommissionEmployee class represents an employee who receives
3 // a base salary in addition to a commission.
4
5 public class BasePlusCommissionEmployee
6 {
7 private String firstName;
8 private String lastName;
9 private String socialSecurityNumber;
10 private double grossSales; // gross weekly sales
11 private double commissionRate; // commission percentage
12 private double baseSalary; // base salary per week
13
14 // six-argument constructor
15 public BasePlusCommissionEmployee( String first, String last,
16 String ssn, double sales, double rate, double salary )
17 {
18 // implicit call to Object constructor occurs here
19 firstName = first;
20 lastName = last;
21 socialSecurityNumber = ssn;
22 setGrossSales( sales ); // validate and store gross sales
23 setCommissionRate( rate ); // validate and store commission rate
24 setBaseSalary( salary ); // validate and store base salary
25 } // end six-argument BasePlusCommissionEmployee constructor
26
27 // set first name
28 public void setFirstName( String first )
29 {
30 firstName = first; // should validate
31 } // end method setFirstName
32
33 // return first name
34 public String getFirstName()
35 {
36 return firstName;
37 } // end method getFirstName
38
39 // set last name
40 public void setLastName( String last )
41 {
42 lastName = last; // should validate
43 } // end method setLastName
44
45 // return last name
46 public String getLastName()
47 {
48 return lastName;
49 } // end method getLastName
50
51 // set social security number
52 public void setSocialSecurityNumber( String ssn )
53 {
54 socialSecurityNumber = ssn; // should validate
55 } // end method setSocialSecurityNumber
56
57 // return social security number
58 public String getSocialSecurityNumber()
59 {
60 return socialSecurityNumber;
61 } // end method getSocialSecurityNumber
62
63 // set gross sales amount
64 public void setGrossSales( double sales )
65 {
66 if ( sales >= 0.0 )
67 grossSales = sales;
68 else
69 throw new IllegalArgumentException(
70 "Gross sales must be >= 0.0" );
71 } // end method setGrossSales
72
73 // return gross sales amount
74 public double getGrossSales()
75 {
76 return grossSales;
77 } // end method getGrossSales
78
79 // set commission rate
80 public void setCommissionRate( double rate )
81 {
82 if ( rate > 0.0 && rate < 1.0 )
83 commissionRate = rate;
84 else
85 throw new IllegalArgumentException(
86 "Commission rate must be > 0.0 and < 1.0" );
87 } // end method setCommissionRate
88
89 // return commission rate
90 public double getCommissionRate()
91 {
92 return commissionRate;
93 } // end method getCommissionRate
94
95 // set base salary
96 public void setBaseSalary( double salary )
97 {
98 if ( salary >= 0.0 )
99 baseSalary = salary;
100 else
101 throw new IllegalArgumentException(
102 "Base salary must be >= 0.0" );
103 } // end method setBaseSalary
104
105 // return base salary
106 public double getBaseSalary()
107 {
108 return baseSalary;
109 } // end method getBaseSalary
110
111 // calculate earnings
112 public double earnings()
113 {
114 return baseSalary + ( commissionRate * grossSales );
115 } // end method earnings
116
117 // return String representation of BasePlusCommissionEmployee
118 @Override // indicates that this method overrides a superclass method
119 public String toString()
120 {
121 return String.format(
122 "%s: %s %s
%s: %s
%s: %.2f
%s: %.2f
%s: %.2f",
123 "base-salaried commission employee", firstName, lastName,
124 "social security number", socialSecurityNumber,
125 "gross sales", grossSales, "commission rate", commissionRate,
126 "base salary", baseSalary );
127 } // end method toString
128 } // end class BasePlusCommissionEmployee
Class BasePlusCommissionEmployee
does not specify “extends Object
” in line 5, so the class implicitly extends Object
. Also, like class CommissionEmployee
’s constructor (lines 13–22 of Fig. G.4), class BasePlusCommissionEmployee
’s constructor invokes class Object
’s default constructor implicitly, as noted in the comment in line 18.
Class BasePlusCommissionEmployee
’s earnings
method (lines 112–115) returns the result of adding the BasePlusCommissionEmployee
’s base salary to the product of the commission rate and the employee’s gross sales.
Class BasePlusCommissionEmployee
overrides Object
method toString
to return a String
containing the BasePlusCommissionEmployee
’s information. Once again, we use format specifier %.2f
to format the gross sales, commission rate and base salary with two digits of precision to the right of the decimal point (line 122).
Figure G.7 tests class BasePlusCommissionEmployee
. Lines 9–11 create a BasePlusCommissionEmployee
object and pass "Bob"
, "Lewis"
, "333-33-3333"
, 5000
, .04
and 300
to the constructor as the first name, last name, social security number, gross sales, commission rate and base salary, respectively. Lines 16–27 use BasePlusCommissionEmployee
’s get methods to retrieve the values of the object’s instance variables for output. Line 29 invokes the object’s setBaseSalary
method to change the base salary. Method setBaseSalary
(Fig. G.6, lines 96–103) ensures that instance variable baseSalary
is not assigned a negative value. Lines 31–33 of Fig. G.7 invoke method toString
explicitly to get the object’s String
representation.
1 // Fig. G.7: BasePlusCommissionEmployeeTest.java
2 // BasePlusCommissionEmployee test program.
3
4 public class BasePlusCommissionEmployeeTest
5 {
6 public static void main( String[] args )
7 {
8 // instantiate BasePlusCommissionEmployee object
9 BasePlusCommissionEmployee employee =
10 new BasePlusCommissionEmployee(
11 "Bob", "Lewis", "333-33-3333", 5000, .04, 300 );
12
13 // get base-salaried commission employee data
14 System.out.println(
15 "Employee information obtained by get methods:
" );
16 System.out.printf( "%s %s
", "First name is",
17 employee.getFirstName() );
18 System.out.printf( "%s %s
", "Last name is",
19 employee.getLastName() );
20 System.out.printf( "%s %s
", "Social security number is",
21 employee.getSocialSecurityNumber() );
22 System.out.printf( "%s %.2f
", "Gross sales is",
23 employee.getGrossSales() );
24 System.out.printf( "%s %.2f
", "Commission rate is",
25 employee.getCommissionRate() );
26 System.out.printf( "%s %.2f
", "Base salary is",
27 employee.getBaseSalary() );
28
29 employee.setBaseSalary( 1000 ); // set base salary
30
31 System.out.printf( "
%s:
%s
",
32 "Updated employee information obtained by toString",
33 employee.toString() );
34 } // end main
35 } // end class BasePlusCommissionEmployeeTest
Employee information obtained by get methods:
First name is Bob
Last name is Lewis
Social security number is 333-33-3333
Gross sales is 5000.00
Commission rate is 0.04
Base salary is 300.00
Updated employee information obtained by toString:
base-salaried commission employee: Bob Lewis
social security number: 333-33-3333
gross sales: 5000.00
commission rate: 0.04
base salary: 1000.00
Much of class BasePlusCommissionEmployee
’s code (Fig. G.6) is similar, or identical, to that of class CommissionEmployee
(Fig. G.4). For example, private
instance variables firstName
and lastName
and methods setFirstName
, getFirstName
, setLastName
and getLastName
are identical to those of class CommissionEmployee
. The classes also both contain private
instance variables socialSecurityNumber
, commissionRate
and grossSales
, and corresponding get and set methods. In addition, the BasePlusCommissionEmployee
constructor is almost identical to that of class CommissionEmployee
, except that BasePlusCommissionEmployee
’s constructor also sets the baseSalary
. The other additions to class BasePlusCommissionEmployee
are private
instance variable baseSalary
and methods setBaseSalary
and getBaseSalary
. Class BasePlusCommissionEmployee
’s toString
method is nearly identical to that of class CommissionEmployee
except that it also outputs instance variable baseSalary
with two digits of precision to the right of the decimal point.
We literally copied code from class CommissionEmployee
and pasted it into class BasePlusCommissionEmployee
, then modified class BasePlusCommissionEmployee
to include a base salary and methods that manipulate the base salary. This “copy-and-paste” approach is often error prone and time consuming. Worse yet, it spreads copies of the same code throughout a system, creating a code-maintenance nightmare. Is there a way to “absorb” the instance variables and methods of one class in a way that makes them part of other classes without duplicating code? Next we answer this question, using a more elegant approach to building classes that emphasizes the benefits of inheritance.