The essence of runtime polymorphic behavior (Method overriding through inheritance)

With runtime polymorphism based on method overriding, the decision as to which version of a method will be executed is based on the actual type of object whose reference is stored in the reference variable, and not on the type of the reference variable on which the method is invoked.

Late binding:
The decision as to which version of the method to invoke cannot be made at compile time.  That decision must be deferred and made at runtime.  This is sometimes referred to as late binding. (Method overriding through inheritance)

 

Operational description of runtime polymorphism

Here is an operational description of runtime polymorphism as implemented in Java through inheritance and method overriding:

1. Assume that a class named Animal defines a method named speak.

2. Assume that a class named Dog extends Animal and overrides the method named speak.

3.Assume that a reference to an object of the class named Dog is assigned to a reference variable named animal of type Animal.

4. Assume that the method named speak is then invoked on the reference variable using the following syntax:  animal.speak()

Result: 
The version of the method named method that will actually be executed is the overridden version in the class named Dog, and is not the version that is defined in the class named Animal.

This is runtime polymorphism, sometimes also referred to as late-binding.

Now lets see how this is used in code;

public class Animal {
    protected void speak() {
        System.out.println("Grr..Grr..");
    }
}
---------------------------------

public class Dog extends Animal {
    public void speak() {
        System.out.println("Bow..Bow..");
    }
}
---------------------------------

This is a small test class:

public class Test {
    public static void main(String[] args) {
        Animal animal= new Dog(); // This is run time polymorphism magic
        ref.speak();
    }
}
---------------------------------

Output:
  Bow..Bow..

Wow, your animal reference is barking and not gr. runtime polymorphism has come in the way to selct relevent speak method!!

Runtime polymorphism is very powerful

At first look, you might feel whats so big fuzz about this. But as you gain more experience with Java, you will learn that much of the power of OOP using Java is centered on runtime polymorphism using class inheritance, interfaces, and method overriding.  (The use of interfaces for polymorphism will be discussed in a subsequent lesson.)

An important attribute of runtime polymorphism

The decision as to which version of the method to execute is based on the actual type of object whose reference is stored in the reference variable, not on the type of the reference variable on which the method is invoked.

Why is it called runtime polymorphism?

The reason that this type of polymorphism is often referred to as runtime polymorphism is because the decision as to which version of the method to execute cannot be made until runtime.  The decision cannot be made at compile time.

Why defer the decision?

The decision cannot be made at compile time because the compiler has no way of knowing (when the program is compiled) the actual type of the object whose reference will be stored in the reference variable .

Are you still a bit confuse? Its natural to take a bit of time to grasp the run time polymorphism for a biginner. But here at javatouch we do not keep room for your confusions :-). So lets have a look at a more generic version of our test class, and you should be able to understand evrything better.

public class Test {

    public static void main(String[] args) {
        Test test = new Test();

        Animal animal = new Dog();
        test.makeSpeak(animal);
    }
   
    /**
     * Make animal speak
     * @param animal
     */

    private void makeSpeak(Animal animal){
        animal.speak();  
    }
}


makeSpeak(Animal animal) method has parameter of Animal type. But run time polymorphism allows it to take different objects (of caurse objects that are sub classed of Animal class) at run time. Pretty cool and making bit more sence ahh.

Ok, now lets say we have another class called Cat which is also a subclass of Animal class.

---------------------------------------

public class Cat extends Animal {
    public void speak() {
        System.out.println("Meaw..Meaw..");
    }
}
---------------------------------------

Now we are going to assign Dog and Cat objects to our Animal refernce and call the makeSpeak(Animal animal) method.

public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        Animal animal;
       // We assign a Dog to the animal reference
        animal = new Dog();
        test.makeSpeak(animal);
       
        // Now our animal reference is assigned to a Cat
        animal = new Cat();
        test.makeSpeak(animal);
    }
   
    /**
     * Make animal speak
     * @param animal
     */

    private void makeSpeak(Animal animal){
        animal.speak();  
    }
}
----------------------------------------

Output:
  Bow..Bow..
  Meaw..Meaw..

Interestingly, our makeSpeak(Animal animal)  method is generic but it calls the correct speak() method of correct (run time) object. This is run time polymorphism using method overriding through inheritance.

Necessary, but not sufficient:

Runtime polymorphism based on class inheritance requires that the type of the reference variable be a superclass of the class from which the object (on which the method will be invoked) is instantiated.

However, while necessary, that is not sufficient.

The type of the reference variable must also be a class that either defines or inherits the method that will ultimately be invoked on the object.

Once again, what is runtime polymorphism?

As I have discussed in this lesson, runtime polymorphic behavior based on inheritance occurs when
* The type of the reference is a superclass of the class from which the object was instantiated
* The version of the method that is executed is the version that is either defined in, or inherited into, the class from which the object was instantiated

More than you ever wanted to hear..

And that is probably more than you ever wanted to hear about runtime polymorphism based on inheritance.

The next page will discuss runtime polymorphism based on the Java interface.  From a practical viewpoint, you will find the rules to be similar but somewhat different in the case of the Java interface.

Reference:
- The Essence of OOP using Java, Runtime Polymorphism through Inheritance

<< Previous  +  Next >>