I'm reading up a book on Java and currently on the Polymorphism
topic as well as how to downcast
a reference variable. However, I'm pretty stuck with understanding the concept of downcasting. Below is the uml for the example I'm following.
For all objects of BasePlusCommissionEmployee
they are to given a 10% increase on their base salary. The other Employee
subclasses are as per normal. The PayrollSystemTest
contains the main method to run the application.
// Fig. 10.9: PayrollSystemTest.java
// Employee hierarchy test program.
public class PayrollSystemTest
{
public static void main(String[] args)
{
// create subclass objects
SalariedEmployee salariedEmployee =
new SalariedEmployee("John", "Smith", "111-11-1111", 800.00);
HourlyEmployee hourlyEmployee =
new HourlyEmployee("Karen", "Price", "222-22-2222", 16.75, 40.0);
CommissionEmployee commissionEmployee =
new CommissionEmployee(
"Sue", "Jones", "333-33-3333", 10000, .06);
BasePlusCommissionEmployee basePlusCommissionEmployee =
new BasePlusCommissionEmployee(
"Bob", "Lewis", "444-44-4444", 5000, .04, 300);
System.out.println("Employee processed individually:");
System.out.printf("%n%s%n%s: $%,.2f%n%n",
salariedEmployee, "earned", salariedEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
hourlyEmployee, "earned", hourlyEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
commissionEmployee, "earned", commissionEmployee.earnings());
System.out.printf("%s%n%s: $%,.2f%n%n",
basePlusCommissionEmployee,
"earned", basePlusCommissionEmployee.earnings());
// create four-element Employee array
Employee[] employees = new Employee[4];
// initialize array with Employees
employees[0] = salariedEmployee;
employees[1] = hourlyEmployee;
employees[2] = commissionEmployee;
employees[3] = basePlusCommissionEmployee;
System.out.printf("Employees processed polymorphically:%n%n");
// generically process each element in array employees
for (Employee currentEmployee : employees)
{
System.out.println(currentEmployee); // invokes toString
// determine whether element is a BasePlusCommissionEmployee
if (currentEmployee instanceof BasePlusCommissionEmployee)
{
// downcast Employee reference to
// BasePlusCommissionEmployee reference
BasePlusCommissionEmployee employee =
(BasePlusCommissionEmployee) currentEmployee;
employee.setBaseSalary(1.10 * employee.getBaseSalary());
System.out.printf(
"new base salary with 10%% increase is: $%,.2f%n",
employee.getBaseSalary());
} // end if
System.out.printf(
"earned $%,.2f%n%n", currentEmployee.earnings());
} // end for
// get type name of each object in employees array
for (int j = 0; j < employees.length; j++)
System.out.printf("Employee %d is a %s%n", j,
employees[j].getClass().getName());
} // end main
} // end class PayrollSystemTest
The book further explains that the enhanced for loop iterates the array employees
and invokes methods toString
and earnings
with Employee
variable currentEmployee
which is assigned the reference to a different Employee
in the array on each iteration. As a result, the output illustrates that the specific methods for each class are invoked and are resolved at execution time, based on the type of the object.
In order to invoke BasePlusCommissionEmployee
's methods getBaseSalary
and setBaseSalary
on the current Employee
object, a condition statement is used to check if the object reference is a BasePlusCommissionEmployee
object by using the instanceof operator and if the condition is true the object has to be downcast from Employee
to BasePlusCommissionEmployee
type before invoking the methods mentioned.
This seriously confuses me because we are able to access the subclasses' toString
method but has to downcast the object in order to use the other methods namely getBaseSalary
and setBaseSalary
? Why is this the case?