next up previous contents
Next: Multiple inheritance Up: Subclasses and inheritance Previous: Subclasses and superclasses   Contents

Inheritance polymorphism

The static type of the variable determines what methods are accessible. If we write

   Employee e = new Manager ( ....)

we are not permitted to write

   System.out.println(e.getSecretary());

even though, at run time, the call to getSecretary() is not a problem.

But, we still have to answer the following. What does

  e.bonus(p)

mean?

There are two possibilities:

  1. Static: e is an Employee, so take the definition of bonus from class Employee.

  2. Dynamic e is declared to be an Employee but is actually a Manager at run time, so take the definition of bonus from Manager.

The dynamic definition is more useful than the static one--it permits the following type of ``generic'' program.

   Employee[] emparray = new Employee[2];
   Employee e = new Employee(...);
   Manager e = new Manager(...);

   emparray[0] = e;
   emparray[1] = m;

   for (i = 0; i < emparray.length; i++){
     System.out.println(emparray[i].bonus(5.0);
   }

Here, emparray[1] will correctly use bonus as defined in Manager.

This ability to choose the appropriate method at run time, based on the identity of the object, is called run time polymorphism or inheritance polymorphism.

This is in contrast to overloading based polymorphism such as the multiplicity of sort methods in the class Arrays, described earlier.

Getting back to the code above, is emparray[1].setSecretary(s) allowed? After all, we know that it is a Manager, even though it is declared Employee.

As mentioned earlier, if a variable is declared to be of type Employee, only methods that are accessible in the class Employee may be used.

However, if we are confident that at run time the object is really a Manager, we may ask for a ``type upgrade'', or a cast. Casting is done using C-like syntax.

  ((Manager) emparray[1]).setSecretary(s)

At run time, if emparray[1] is not a Manager, the cast will fail (rather than call an absurd method) and the program will crash. Casting can only be done between compatible types--that is, from a class to one of its descendants.

We can check whether emparray[1] is a Manager at run time using the predicate instanceof. To be safe, we can write:

  if (emparray[1] instanceof Manager){
    ((Manager) emparray[1]).setSecretary(s);
  }

This is a trivial example of a property called reflection. Reflection is used in the philosophical sense to refer to a language that can ``think about itself''. Java is rich in reflective capabilities. We will discuss this again later.


next up previous contents
Next: Multiple inheritance Up: Subclasses and inheritance Previous: Subclasses and superclasses   Contents
Madhavan Mukund 2004-04-29