6.5 Making Changes in Class Hierarchy
6.5.2 Change in Property Definition for Some Subclasses
In some situations, a change in property definition at the superclass level may not necessarily apply to all subclasses. The above solution would therefore not apply in these situations. To illustrate, let us extend the Person class hierarchy further to in- clude two more employee classes: Technician and Clerk.
Let us assume the following for a HomeCare employee:
• a manager—basic salary plus allowance;
• a salesperson—basic salary plus commission;
• a secretary—basic salary;
• a technician—basic salary;
• a clerk—basic salary.
At the Employee class, a getPay() method is defined to return the monthly pay of an employee since the method applies to all classes of employee. The definition of the Person class remains the same as before:
class Person {
private String name;
Person(String aName) {name=aName;}
public String getName() { return name; } }
Inheritance 69 Employee extends Person as follows:
As before, main() is defined in the Employee class with additional code for Technician and Clerk class highlighted in bold. There is no change in class definition for Manager and Secretary. Technician and Clerk extend Employee, since they are subclasses of Employee:
Executing main() produces the following output:
The Manager Simon (employee number 01234M) has a pay of 9000 The Secretary Selene (employee number 98765S) has a pay of 2500 The Technician Terrence (employee number 42356T) has a pay of 2000 The Clerk Charmaine (employee number 68329C) has a pay of 1200 class Employee extends Person {
private float basicSalary;
private String employeeNumber;
Employee(String aName, String aEmployeeNumber, float aBasicSalary) {
super(aName);
employeeNumber = aEmployeeNumber;
basicSalary = aBasicSalary;
}
public String getEmployeeNumber() { return employeeNumber; } public float getBasicSalary() { return basicSalary; } public float getPay() { return basicSalary; }
public static void main(String argv[]) {
Technician t = new Technician("Terrence", "42356T", 2000.0f);
Clerk c = new Clerk("Charmaine", "68329C", 1200.0f);
} }
class Technician extends Employee {
Technician (String aName, String aEmployeeNumber, float aBasicSalary) {
super(aName, aEmployeeNumber, aBasicSalary);
} }
class Clerk extends Employee {
Clerk (String aName, String aEmployeeNumber, float aBasicSalary) {
super(aName, aEmployeeNumber, aBasicSalary);
} }
Manager m = new Manager("Simon", "01234M", 9000.0f, 2000.0f);
Secretary s = new Secretary("Selene", "98765S", 2500.0f);
System.out.print("The Manager "+m.getName()+
" (employee number "+m.getEmployeeNumber()+")");
System.out.println(" has a pay of "+m.getPay());
System.out.print("The Secretary "+s.getName()+
" (employee number "+s.getEmployeeNumber()+")");
System.out.print("The Technician "+t.getName()+
System.out.println(" has a pay of "+s.getPay());
" (employee number "+t.getEmployeeNumber()+")");
System.out.println(" has a pay of "+t.getPay());
System.out.print("The Clerk "+c.getName()+
" (employee number "+c.getEmployeeNumber()+")");
System.out.println(" has a pay of "+c.getPay());
70 Object-Oriented Programming and Java
A cursory examination of the output reveals an inaccuracy in the manager’s pay: an omission of allowance amounting to $2000. What has gone wrong?
Manager
employee number basicSalary
getEmployeeNumber() getBasicSalary()
allowance getAllowance() getPay()
Secretary Technician Clerk getPay() getPay() getPay()
Employee
Figure 6-5: Extended Employee class hierarchy.
The above problem can be approached in two ways:
• Remove the getPay() method from the Employee class and define it indi- vidually in the subclasses (Secretary, Technician, Clerk, and Manager).
• Maintain the definition of getPay() method in Employee class and rede- fine it in the Manager class.
Figure 6-5 illustrates a class diagram for the first approach. Each of the sub- classes has its own implementation of the getPay() method. One disadvantage of this approach is that the definition of the getPay() method has to be repeated in all the subclasses. This is highly inefficient and can be difficult to maintain especially in situations where the number of subclasses is large.
Manager
Employee
employee number basicSalary
getEmployeeNumber() getBasicSalary() getPay()
allowance getAllowance() getPay()
Secretary Technician Clerk
Figure 6-6: Redefining getPay() method of Manager.
Inheritance 71 In the second approach, the definition of the getPay() method is maintained at the Employee class but redefined in the Manager class. This ensures that the getPay() method is inherited by all subclasses of Employee, including the Manager class.
Since a similar getPay() method is defined in Manager, the getPay() method of the Manager class would be used in the resolution of method call by the object- oriented system instead. This is depicted in Figure 6-6 and Listing 6-2.
The getPay() method of the Manager class is said to redefine the getPay() method of the Employee class. Note that a redefined method has the same method name and parameter definition of a redefining method. While a redefining method has the same method signature with the redefined method, the implementation of the methods may differ. In this case, the getPay() method of the Manager class includes an additional computation of the allowance component.
Listing 6-2: Redefining the getPay() method.
Judging from the output of the two solutions, both approaches are correct:
The Manager Simon (employee number 01234M) has a pay of 11000
The Secretary Selene (employee number 98765S) has a pay of 2500 The Technician Terrence (employee number 42356T) has a pay of 2000 The Clerk Charmaine (employee number 68329C) has a pay of 1200
class Person { ...
}
class Employee extends Person { ...
public float getPay() { return basicSalary; } public static void main(String argv[]) { ...
} }
class Manager extends Employee { private float allowance;
Manager(String aName, String aEmployeeNumber, float aBasicSalary, float aAllowanceAmt) { super(aName, aEmployeeNumber, aBasicSalary);
allowance = aAllowanceAmt;
}
public float getAllowance() { return allowance;
}
public float getPay() {
return (basicSalary + allowance);
} }
class Secretary extends Employee { ...
}
class Technician extends Employee { ...
}
class Clerk extends Employee { ...
}
72 Object-Oriented Programming and Java
However, the second approach is better than the first approach as it enhances software reuse and minimizes the effect of change on other classes. Redefinition of methods is supported in object-oriented programming and closely connected with operation overloading. We will further discuss operation overloading in the next chapter.