Java Polymorphism

What is Polymorphism in Java?

Polymorphism is a fundamental concept in Object-Oriented Programming (OOP) that allows objects to take on many forms. The term “polymorphism” is derived from two Greek words: “poly,” meaning many, and “morph,” meaning forms. In Java, polymorphism enables methods to perform different tasks based on the object that invokes them.

Why Use Polymorphism?

  1. Code Reusability: Write a single method and reuse it with different implementations.
  2. Flexibility: Handle different objects with a common interface.
  3. Simplified Maintenance: Change behavior in one place without affecting other parts of the code.
  4. Extensibility: Add new functionalities without modifying existing code.

Types of Polymorphism in Java

Java supports two types of polymorphism:

  1. Compile-Time Polymorphism (Static Binding)
    This is achieved through method overloading. The method to call is resolved at compile-time based on the method signature.
  2. Run-Time Polymorphism (Dynamic Binding)
    This is achieved through method overriding. The method to call is resolved at runtime based on the actual object type.

Compile-Time Polymorphism

Method Overloading occurs when two or more methods in the same class have the same name but different parameters (number, type, or order of parameters).

Example of Method Overloading:

class Calculator {
// Method with two parameters
int add(int a, int b) {
return a + b;
}

// Overloaded method with three parameters
int add(int a, int b, int c) {
return a + b + c;
}
}

public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("Sum of two numbers: " + calc.add(10, 20));
System.out.println("Sum of three numbers: " + calc.add(10, 20, 30));
}
}

Output:

Sum of two numbers: 30  
Sum of three numbers: 60

Run-Time Polymorphism

Method Overriding occurs when a subclass provides a specific implementation for a method already defined in its parent class. To achieve runtime polymorphism, the parent class reference is used to call overridden methods in the child class.

Example of Method Overriding:

class Animal {
void sound() {
System.out.println("This is a generic animal sound.");
}
}

class Dog extends Animal {
@Override
void sound() {
System.out.println("The dog barks.");
}
}

class Cat extends Animal {
@Override
void sound() {
System.out.println("The cat meows.");
}
}

public class Main {
public static void main(String[] args) {
Animal animal;

animal = new Dog();
animal.sound(); // Calls Dog's sound method

animal = new Cat();
animal.sound(); // Calls Cat's sound method
}
}

Output:

The dog barks.  
The cat meows.

Key Differences Between Compile-Time and Run-Time Polymorphism

AspectCompile-Time PolymorphismRun-Time Polymorphism
BindingStatic (resolved at compile-time)Dynamic (resolved at runtime)
MethodOverloadingOverriding
Inheritance NeededNoYes
PerformanceFasterSlower due to runtime resolution

Polymorphism with Interfaces

Java allows achieving polymorphism through interfaces, where multiple classes implement the same interface with their own versions of the methods.

Example of Polymorphism Using Interfaces:

interface Vehicle {
void start();
}

class Car implements Vehicle {
public void start() {
System.out.println("Car starts with a key.");
}
}

class Bike implements Vehicle {
public void start() {
System.out.println("Bike starts with a kick.");
}
}

public class Main {
public static void main(String[] args) {
Vehicle v;

v = new Car();
v.start();

v = new Bike();
v.start();
}
}

Output:

Car starts with a key.  
Bike starts with a kick.

Polymorphism in Real Life

Consider a payment system. A common interface Payment could represent multiple types of payments, such as CreditCardPayment or UPIPayment. Each payment type implements its own method for processing payments, demonstrating polymorphism.

interface Payment {
void makePayment();
}

class CreditCardPayment implements Payment {
public void makePayment() {
System.out.println("Payment made using Credit Card.");
}
}

class UPIPayment implements Payment {
public void makePayment() {
System.out.println("Payment made using UPI.");
}
}

public class Main {
public static void main(String[] args) {
Payment payment;

payment = new CreditCardPayment();
payment.makePayment();

payment = new UPIPayment();
payment.makePayment();
}
}

Output:

Payment made using Credit Card.  
Payment made using UPI.

Advantages of Polymorphism

  1. Simplifies Code: Reduces complexity by enabling a single interface for multiple implementations.
  2. Extensibility: Easily add new functionality without modifying existing code.
  3. Code Reusability: Use a single method for different types of objects.
  4. Improved Maintainability: Makes the code cleaner and easier to update.

Leave a Comment