This section offers an inheritance example that extends, once again, the functionality of the Person class given in chapter 9. Figure 11-19 gives the UML diagram.
Figure 11-19: Employee Class Inheritance Hierarchy
Referring to figure 11-19 — The Employee class extends Person and implements the Payable interface. However, in this example, as you will see below, the implementation of the method specified in the Payable interface, pay(), is deferred by the Employee class to its derived classes. Because the pay() method is not actually implemented in the Employee class the Employee class must be declared to be abstract.
HourlyEmployee and SalariedEmployee extend the functionality of Employee. Each of these classes will implement the pay() method in their own special way.
From a polymorphic point of view you could write a program that uses these classes in several ways, it just depends on which set of interface methods you want to target. For instance, you could write a program that contains an array of Person references. Each of these Person references could then be initialized to point to an HourlyEmployee object or a SalariedEmployee object. In either case the only methods you can call, without casting, on these objects via a Person reference are those public methods specified by the Person class.
Another approach would be to declare an array of Payable references. Then again you could initialize each Payable reference to point to either an HourlyEmployee object or a SalariedEmployee object. Now the only method you can call on each of these objects, without casting, is the pay() method.
A third approach would be to declare an array of Employee references and initialize each reference to point to either an HourlyEmployee object or a SalariedEmployee object. In this scenario you could then call any method specified by Person, Payable, and Employee. This is the approach taken in the EmployeeTestApp program listed below.
The code for each of these classes (except Person which was shown earlier in the chapter) is given in examples 11.20 through 11.24.
Example 11.20: Payable.java
1 interface Payable { 2 double pay(); 3 }
Example 11.21: Employee.java
1 public abstract class Employee extends Person implements Payable { 2 private String _employee_number = null; 3 4 public Employee(String f_name, String m_name, String l_name, int dob_year, int dob_month, 5 int dob_day, String gender, String employee_number){ 6 super(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender); 7 _employee_number = employee_number; 8 } 9 10 public String getEmployeeNumber(){ 11 return _employee_number; 12 } 13 14 public String getEmployeeInfo(){ 15 return getEmployeeNumber() + " " + getFirstName() + " " + getLastName(); 16 } 17 }
Example 11.22: HourlyEmployee.java
1 public class HourlyEmployee extends Employee { 2 private double _hours_worked; 3 private double _hourly_wage_rate; 4 5 public HourlyEmployee(String f_name, String m_name, String l_name, int dob_year, int dob_month, 6 int dob_day, String gender, String employee_number, 7 double hourly_wage_rate, double hours_worked){ 8 super(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender, employee_number); 9 _hourly_wage_rate = hourly_wage_rate; 10 _hours_worked = hours_worked; 11 } 12 13 public double pay(){ 14 return _hourly_wage_rate * _hours_worked; 15 } 16 }
Example 11.23: SalariedEmployee.java
1 public class SalariedEmployee extends Employee { 2 private double _annual_salary; 3 4 public SalariedEmployee(String f_name, String m_name, String l_name, int dob_year, int dob_month, 5 int dob_day, String gender, String employee_number, double annual_salary){ 6 super(f_name, m_name, l_name, dob_year, dob_month, dob_day, gender, employee_number); 7 _annual_salary = annual_salary; 8 } 9 10 public double pay(){ 11 return _annual_salary/24; // 24 pay periods 12 } 13 }
Example 11.24: EmployeeTestApp.java
1 import java.text.*; 2 3 public class EmployeeTestApp { 4 public static void main(String[] args){ 5 Employee[] employees = new Employee[4]; 6 NumberFormat number_format = NumberFormat.getInstance(); 7 number_format.setMaximumFractionDigits(2); 8 9 employees[0] = new SalariedEmployee("Steve", "J", "Jones", 1983, 3, 4, "M", 10 "000-11111", 65000.00); 11 employees[1] = new HourlyEmployee("Bob", "E", "Evans", 1992, 1, 2, "M", 12 "000-22222", 23.00, 80.00); 13 employees[2] = new SalariedEmployee("Janice", "A", "Brown", 1983, 3, 4, "F", 14 "000-33333", 100000.00); 15 employees[3] = new HourlyEmployee("Helen", "Of", "Troy", 1946, 4, 8, "F", 16 "000-44444", 50.00, 80.00); 17 18 for(int i = 0; i<employees.length; i++){ 19 System.out.println("Employee: " + employees[i].getEmployeeInfo() + 20 " Pay: " + "$" + number_format.format(employees[i].pay())); 21 } 22 } 23 }
Referring to example 11.24 — the EmployeeTestApp program declares an array of Employee references on line 5 named employees. On lines 9 through 16 it initializes each Employee reference to point to either an HourlyEmployee or SalariedEmployee object.
In the for statement on line 18 each Employee object is manipulated polymorphically via the interface specified by the Employee class. (Which includes the interfaces inherited from Person and Payable.) The results of running this program are shown in figure 11-20.
Figure 11-20: Results of Running Example 11.24