What is Polymorphism?
Polymorphism is an important concept in Object-Oriented Programming (OOP). The word “Polymorphism” means “many forms.” It allows objects of different types to be treated as objects of a common type. This makes the code more flexible and easier to maintain.
Types of Polymorphism
Polymorphism is divided into two main types:
- Compile-time Polymorphism (Method Overloading)
- Run-time Polymorphism (Method Overriding)
1. Compile-time Polymorphism (Method Overloading)
Compile-time polymorphism happens when multiple methods in the same class have the same name but different parameters. The compiler determines which method to call based on the method signature.
Example of Method Overloading in Java
class MathOperations {
// Method to add two integers
int add(int a, int b) {
return a + b;
}
// Method to add three integers
int add(int a, int b, int c) {
return a + b + c;
}
// Method to add two double values
double add(double a, double b) {
return a + b;
}
public static void main(String[] args) {
MathOperations obj = new MathOperations();
System.out.println("Sum of 2 and 3: " + obj.add(2, 3));
System.out.println("Sum of 2, 3, and 4: " + obj.add(2, 3, 4));
System.out.println("Sum of 2.5 and 3.5: " + obj.add(2.5, 3.5));
}
}
Output:
Sum of 2 and 3: 5
Sum of 2, 3, and 4: 9
Sum of 2.5 and 3.5: 6.0
Key Points:
- Method overloading allows multiple methods with the same name but different parameters.
- It improves code readability and reduces redundancy.
2. Run-time Polymorphism (Method Overriding)
Run-time polymorphism occurs when a subclass provides a different implementation of a method already defined in its parent class. The method in the subclass must have the same name and parameters.
Example of Method Overriding in Java
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal;
myAnimal = new Dog();
myAnimal.makeSound(); // Calls Dog's method
myAnimal = new Cat();
myAnimal.makeSound(); // Calls Cat's method
}
}
Output:
Dog barks
Cat meows
Key Points:
- Method overriding allows a subclass to provide a custom implementation of a method in its parent class.
- The @Override annotation ensures the method correctly overrides the superclass method.
- The method to execute is determined at runtime, depending on the actual object type.
Polymorphism with Interfaces
Polymorphism is also achieved using interfaces. Different classes can implement the same interface and define their own versions of the methods.
Example using Interfaces
interface Vehicle {
void start();
}
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car starts with a key");
}
}
class Bike implements Vehicle {
@Override
public void start() {
System.out.println("Bike starts with a button");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myVehicle;
myVehicle = new Car();
myVehicle.start(); // Calls Car's start method
myVehicle = new Bike();
myVehicle.start(); // Calls Bike's start method
}
}
Output:
Car starts with a key
Bike starts with a button
Key Points:
- Interfaces support polymorphism by allowing different classes to implement the same methods differently.
- The method that executes depends on the actual object type.
Polymorphism with Abstract Classes
Abstract classes also enable polymorphism by requiring subclasses to provide their own implementations of abstract methods.
Example using Abstract Classes
abstract class Animal {
abstract void makeSound();
}
class Cow extends Animal {
@Override
void makeSound() {
System.out.println("Cow moos");
}
}
class Sheep extends Animal {
@Override
void makeSound() {
System.out.println("Sheep bleats");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal;
myAnimal = new Cow();
myAnimal.makeSound(); // Calls Cow's method
myAnimal = new Sheep();
myAnimal.makeSound(); // Calls Sheep's method
}
}
Output:
Cow moos
Sheep bleats
Key Points:
- Abstract classes support polymorphism by requiring subclasses to define their own version of an abstract method.
- The method execution is determined at runtime based on the object type.
Advantages of Polymorphism
✔ Code Reusability: Allows the same method name to be used in multiple ways.
✔ Flexibility: Objects can take multiple forms, making the code adaptable.
✔ Scalability: New subclasses can be added without modifying existing code.
✔ Improves Readability: Reduces code duplication and enhances clarity.
Key Differences Between Method Overloading and Method Overriding
Feature | Method Overloading | Method Overriding |
---|---|---|
Definition | Same method name, different parameters. | Subclass provides a new implementation of a superclass method. |
Binding Type | Compile-time (Static) | Runtime (Dynamic) |
Inheritance Needed | ❌ No | ✅ Yes |
Parameters | Must be different | Must be the same |
Return Type | Can be different | Must be the same or a subclass of the original return type |
Conclusion
Polymorphism is a powerful OOP concept that enhances code flexibility, readability, and maintainability.