The word “polymorphism” means “many forms,” and in programming, it refers to the ability of an object or method to take on multiple forms. It is one of the key principles of Object-Oriented Programming (OOP), which allows one interface to be used for a general class of actions. It enables objects to be processed in multiple forms.
Polymorphism allows for flexibility and scalability in a program by letting the same method or object behave differently in different scenarios.
Table of Contents
Types of Polymorphism in Java
There are two types of polymorphism in Java:
- Compile-time Polymorphism (Static Polymorphism)
- Run-time Polymorphism (Dynamic Polymorphism)
Let’s explore each in detail, with examples.
1. Compile-time Polymorphism (Static Polymorphism)
Compile-time polymorphism occurs when the compiler resolves the method call at compile time. This is achieved using method overloading or operator overloading (Java does not support operator overloading so we will focus on method overloading).
Method Overloading
Method overloading is when multiple methods in the same class share the same name but have different parameters (type, number, or both). The correct method to call is determined by the parameters used during the method call, at compile time.
Example:
class overloadingExample {
// Method 1: Add two integers
public int add(int a, int b) {
return a + b;
}
// Method 2: Add three integers (Overloaded method)
public int add(int a, int b, int c) {
return a + b + c;
}
// Method 3: Add two doubles (Overloaded method)
public double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
overloadingExample over = new overloadingExample();
// Calls the first method
System.out.println(over.add(100, 200)); // Output: 300
// Calls the second method (overloaded)
System.out.println(over.add(100, 200, 300)); // Output: 600
// Calls the third method (overloaded)
System.out.println(over.add(100.5, 200.5)); // Output: 301.0
}
}
In the above example, the add()
method is overloaded to handle different types of arguments. The appropriate method is selected based on the number and type of arguments passed during the method call.
Characteristics of Compile-time Polymorphism:
- It occurs at compile time.
- Achieved via method overloading.
- Java doesnโt support operator overloading.
- Provides better performance due to early binding.
2. Run-time Polymorphism (Dynamic Polymorphism)
Run-time polymorphism occurs when the method to be invoked is determined at runtime, not at compile time. This is achieved through method overriding and interfaces in Java.
Method Overriding
Method overriding occurs when a subclass provides a specific implementation of a method that is already defined by its parent class. At runtime, the method of the subclass is invoked, not the parent class’s method.
Example:
class Animal {
// Base method
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
// Overriding method
@Override
public void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
// Overriding method
@Override
public void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Animal reference, Animal object
Animal myDog = new Dog(); // Animal reference, Dog object
Animal myCat = new Cat(); // Animal reference, Cat object
// Calls the method based on the actual object type, not reference type
myAnimal.sound(); // Output: Animal makes a sound
myDog.sound(); // Output: Dog barks
myCat.sound(); // Output: Cat meows
}
}
In this example, even though the objects myDog
and myCat
are of type Animal
, the overridden methods in the Dog
and Cat
classes are called at runtime. This is dynamic polymorphism or method overriding.
Characteristics of Run-time Polymorphism:
- It occurs at runtime.
- Achieved through method overriding.
- Late binding (deciding which method to call) occurs during runtime.
- Allows for flexibility and extensibility in code.
Polymorphism with Interfaces
An interface in Java is a way to achieve polymorphism. A class can implement multiple interfaces, and the methods defined by the interfaces can be overridden in the implementing class.
Example:
interface Vehicle {
void start();
}
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car starts with key");
}
}
class Bike implements Vehicle {
@Override
public void start() {
System.out.println("Bike starts with kick");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myCar = new Car();
Vehicle myBike = new Bike();
// Calls the overridden methods of the respective classes
myCar.start(); // Output: Car starts with key
myBike.start(); // Output: Bike starts with kick
}
}
Here, the Vehicle
interface is implemented by both the Car
and Bike
classes, which provide their own implementations of the start()
method. When start()
is called on the Vehicle
reference, the correct implementation is chosen based on the actual object type at runtime.
Differences Between Compile-time and Run-time Polymorphism:
Feature | Compile-time Polymorphism | Run-time Polymorphism |
---|---|---|
Resolution | Resolved at compile time | Resolved at runtime |
Method | Achieved through overloading | Achieved through overriding |
Binding | Early binding (static) | Late binding (dynamic) |
Flexibility | Less flexible | More flexible |
Performance | Generally faster | Slightly slower |
Example | Method Overloading | Method Overriding |
Advantages of Polymorphism
- Code Reusability: Polymorphism allows you to use the same method names for different purposes, reducing redundancy and increasing code reuse.
- Extensibility: Using polymorphism with inheritance and interfaces allows you to extend functionality without modifying existing code.
- Flexibility: With dynamic polymorphism, the program can choose the appropriate method or behavior at runtime, allowing for more flexible and adaptive programs.
Conclusion
Polymorphism in Java is a powerful concept that enhances the flexibility, extensibility, and maintainability of code. Through compile-time polymorphism (method overloading) and run-time polymorphism (method overriding), Java provides the ability to handle many forms of method calls and object behaviors, making it easier to write dynamic and scalable programs.
Whether it’s overloading methods to handle various parameter sets or overriding them to provide specialized behavior in subclasses, polymorphism ensures that Java applications can scale smoothly as the program’s complexity grows. It helps developers achieve clean, organized, and maintainable code that can adapt to new requirements with minimal changes.
People Also Ask
1. What is polymorphism in Java?
Polymorphism in Java is the ability of a method or object to take on multiple forms, allowing one interface to be used for different actions. It enables flexibility by allowing objects and methods to behave differently based on the context.
2. What are the types of polymorphism in Java?
There are two types of polymorphism in Java:
- Compile-time polymorphism (Static Polymorphism) is achieved through method overloading.
- Run-time polymorphism (Dynamic Polymorphism) is achieved through method overriding.
3. How does compile-time polymorphism work in Java?
Compile-time polymorphism in Java occurs through method overloading, where multiple methods share the same name but have different parameter lists. The correct method is determined at compile time.
4. What is method overloading in Java?
Method overloading occurs when a class has multiple methods with the same name but different parameters. The appropriate method is selected based on the argument types and numbers at compile time.
5. How does run-time polymorphism work in Java?
Run-time polymorphism in Java is achieved through method overriding, where a subclass provides its own implementation of a method that is already defined in its superclass. The correct method is invoked at runtime based on the object type.
6. What is method overriding in Java?
Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its parent class. It allows dynamic method dispatch during runtime.
7. Can polymorphism be achieved using interfaces in Java?
Yes, polymorphism can be achieved through interfaces. A class can implement multiple interfaces and provide its own implementations for the methods defined in the interfaces, allowing flexibility and dynamic method invocation.
8. What is the difference between compile-time and run-time polymorphism?
Compile-time polymorphism (method overloading) is resolved at compile time and uses static binding. Run-time polymorphism (method overriding) is resolved at runtime and uses dynamic binding.
9. Which type of polymorphism is more flexible in Java?
Run-time polymorphism is more flexible because the method to be invoked is determined at runtime, allowing for more dynamic and adaptable behavior based on the actual object type.
10. What are the advantages of polymorphism in Java?
Polymorphism in Java improves code reusability, extensibility, and flexibility. It allows for dynamic method invocation, enabling easier maintenance and scalability of applications.