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:
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.