Easy Tutorial
❮ Thread Procon Java Arraylist Sort ❯

Polymorphism in Java


Polymorphism is the ability for the same behavior to have multiple different manifestations or forms.

Polymorphism is the same interface being used with different instances to perform different operations, as shown in the figure:

Polymorphism is the manifestation of multiple forms of an object.

In real life, for example, the action of pressing the F1 key:

The same event occurring on different objects produces different results.

Advantages of Polymorphism

Three Necessary Conditions for Polymorphism

When using polymorphism to call methods, it first checks if the method exists in the parent class. If not, a compile error occurs; if it does, it then calls the method of the subclass.

The benefits of polymorphism: It allows for good program extensibility and can handle all class objects generically.

Below is a demonstration of a polymorphism example, detailed explanations can be found in the comments:

Test.java File Code:

public class Test {
    public static void main(String[] args) {
        show(new Cat());  // Call show method with Cat object
        show(new Dog());  // Call show method with Dog object

        Animal a = new Cat();  // Upcasting
        a.eat();               // Calls Cat's eat
        Cat c = (Cat)a;        // Downcasting
        c.work();              // Calls Cat's work
    }

    public static void show(Animal a) {
        a.eat();
        // Type checking
        if (a instanceof Cat) {  // Cat's actions
            Cat c = (Cat)a;
            c.work();
        } else if (a instanceof Dog) {  // Dog's actions
            Dog c = (Dog)a;
            c.work();
        }
    }
}

abstract class Animal {
    abstract void eat();
}

class Cat extends Animal {
    public void eat() {
        System.out.println("Eating fish");
    }
    public void work() {
        System.out.println("Catching mice");
    }
}

class Dog extends Animal {
    public void eat() {
        System.out.println("Eating bones");
    }
    public void work() {
        System.out.println("Guarding the house");
    }
}

Executing the above program, the output is:

Eating fish
Catching mice
Eating bones
Guarding the house
Eating fish
Catching mice

Virtual Function

The existence of virtual functions is for polymorphism.

Java does not have the concept of virtual functions; its regular functions are equivalent to C++'s virtual functions, with dynamic binding being Java's default behavior. If you do not want a function in Java to have virtual function characteristics, you can add the final keyword to make it a non-virtual function. We will introduce how the behavior of overridden methods in Java affects polymorphism when designing classes.

We have discussed method overriding, which means that a subclass can override a method of its superclass.

When an overridden method is called by a subclass object, the method of the subclass is invoked, not the overridden method in the superclass.

To call the overridden method in the superclass, the keyword super must be used.

Employee.java File Code:

/* File name : Employee.java */
public class Employee {
   private String name;
   private String address;
   private int number;
   public Employee(String name, String address, int number) {
      System.out.println("Employee Constructor");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name
       + " " + this.address);
   }
   public String toString() {
      return name + " " + address + " " + number;
   }
   public String getName() {
      return name;
   }
   public String getAddress() {
      return address;
   }
   public void setAddress(String newAddress) {
      address = newAddress;
   }
   public int getNumber() {
     return number;
   }
}

Suppose the following class inherits from the Employee class:

Salary.java File Code:

/* File name : Salary.java */
public class Salary extends Employee
{
   private double salary; // Annual salary
   public Salary(String name, String address, int number, double salary) {
       super(name, address, number);
       setSalary(salary);
   }
   public void mailCheck() {
       System.out.println("Within mailCheck of Salary class ");
       System.out.println("Mailing check to " + getName()
       + " with salary " + salary);
   }
   public double getSalary() {
       return salary;
   }
   public void setSalary(double newSalary) {
       if(newSalary >= 0.0) {
          salary = newSalary;
       }
   }
   public double computePay() {
      System.out.println("Calculating salary pay for " + getName());
      return salary/52;
   }
}

Now, let's carefully read the following code and try to give its output:

VirtualDemo.java File Code:

/* File name : VirtualDemo.java */
public class VirtualDemo {
   public static void main(String [] args) {
      Salary s = new Salary("Employee A", "Beijing", 3, 3600.00);
      Employee e = new Salary("Employee B", "Shanghai", 2, 2400.00);
      System.out.println("Calling mailCheck using Salary reference -- ");
      s.mailCheck();
System.out.println("\nUsing Employee reference to call mailCheck--");
e.mailCheck();
}
}

The above example compiles and runs as follows:

Employee constructor
Employee constructor
Using Salary reference to call mailCheck -- 
mailCheck method of Salary class 
Mailing check to: Employee A, salary: 3600.0

Using Employee reference to call mailCheck--
mailCheck method of Salary class 
Mailing check to: Employee B, salary: 2400.0

Example Analysis

-

In the example, two Salary objects are instantiated: one using a Salary reference s, and the other using an Employee reference e.

-

When calling s.mailCheck(), the compiler finds mailCheck() in the Salary class at compile time, and the JVM calls the mailCheck() method of the Salary class during execution.

-

e is a reference to Employee, but the reference e ultimately runs the mailCheck() method of the Salary class.

-

At compile time, the compiler uses the mailCheck() method in the Employee class to verify the statement, but during runtime, the Java Virtual Machine (JVM) calls the mailCheck() method of the Salary class.

This entire process is known as virtual method invocation, and the method is called a virtual method.

All methods in Java can behave in this way, so overridden methods can be called at runtime, regardless of the data type of the reference variable in the source code at compile time.


Polymorphism Implementation Methods

Method One: Overriding:

Method Two: Interfaces

-

  1. The most representative interface in real life is the socket, such as a three-pronged plug that can be plugged into a three-hole socket, because this is a standardized interface rule in each country. It may not work abroad because of the different defined interface types there.

-

  1. Interfaces in Java are similar to real-life interfaces, being a collection of method signatures without method implementations. For more details, see the Java Interfaces section.

Method Three: Abstract Classes and Abstract Methods

For more details, see the Java Abstract Classes section.

❮ Thread Procon Java Arraylist Sort ❯