
Polymorphism is one of the core concepts of Object-Oriented Programming (OOP), and Java is no exception in utilizing this powerful feature. In simple terms, polymorphism allows objects of different classes to be treated as objects of a common superclass. The primary benefit of polymorphism is that it enables one interface to be used for a general class of actions, making your code more flexible and reusable.
In this article, we’ll explore a Java polymorphism example that demonstrates how polymorphism works in Java.
Types of Polymorphism in Java
Polymorphism in Java can be understood in two main types:
- Compile-Time Polymorphism (Method Overloading): This type of polymorphism occurs when multiple methods have the same name but differ in parameters (number or type of parameters).
- Runtime Polymorphism (Method Overriding): This type of polymorphism occurs when a subclass redefines a method of its superclass, allowing the method to behave differently based on the object type.
Both types of polymorphism help achieve more flexible and maintainable code.
Java Polymorphism Example: Method Overloading (Compile-Time Polymorphism)
Let’s first look at method overloading to understand how compile-time polymorphism works. Here’s an example:
javaCopyclass Calculator {
// Overloaded method for adding two integers
public int add(int a, int b) {
return a + b;
}
// Overloaded method for adding three integers
public int add(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
// Calling the method with two parameters
System.out.println("Sum of two numbers: " + calculator.add(5, 10));
// Calling the method with three parameters
System.out.println("Sum of three numbers: " + calculator.add(5, 10, 15));
}
}
In this example, the method add
is overloaded with two different signatures. The Java compiler determines which method to call based on the number of arguments passed, demonstrating compile-time polymorphism.
Java Polymorphism Example: Method Overriding (Runtime Polymorphism)
Next, let’s look at method overriding, which is an example of runtime polymorphism. In this case, a subclass provides its own implementation of a method already defined in its superclass.
javaCopyclass Animal {
// Method in superclass
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
// Method overriding in subclass
@Override
public void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
// Method overriding in subclass
@Override
public void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();
myAnimal.sound(); // Output: Animal makes a sound
myDog.sound(); // Output: Dog barks
myCat.sound(); // Output: Cat meows
}
}
In this example, the sound
method is defined in the superclass Animal
. However, both Dog
and Cat
classes override this method. When we call sound
on an Animal
reference that points to a Dog
or Cat
object, Java determines the method to execute at runtime, which is a clear example of runtime polymorphism.
Benefits of Polymorphism in Java
- Flexibility: Polymorphism allows you to write more flexible code. For instance, you can create a collection of objects that share the same superclass type but have different behaviors.
- Code Reusability: By using polymorphism, you can reuse methods in different contexts without changing the original implementation.
- Maintainability: Polymorphism helps in reducing code duplication and allows easier modifications.
Real-Life Example of Java Polymorphism
To understand Java Polymorphism more clearly, let’s look at some real-life examples of both Compile-Time Polymorphism (Method Overloading) and Runtime Polymorphism (Method Overriding).
1. Compile-Time Polymorphism (Method Overloading)
Real-Life Scenario: Imagine you are booking a hotel room. The method to book the room could be used in different scenarios based on how many people are going to stay in the room.
- Overloaded Method Example:
- One version of the
bookRoom
method takes one parameter (the number of people). - Another version of the method takes two parameters: one for the number of people and another for additional requests (such as a bed type or special accommodations).
- One version of the
This is a real-life scenario where you need multiple ways to call the same method depending on the situation.
javaCopyclass Hotel {
// Method for booking a room for a single person
public void bookRoom(int people) {
System.out.println("Booking a room for " + people + " person.");
}
// Overloaded method for booking a room with special requests
public void bookRoom(int people, String specialRequest) {
System.out.println("Booking a room for " + people + " person with special request: " + specialRequest);
}
}
public class Main {
public static void main(String[] args) {
Hotel hotel = new Hotel();
// Calling the method for one person
hotel.bookRoom(1);
// Calling the overloaded method for two people with a special request
hotel.bookRoom(2, "King size bed");
}
}
Explanation:
- The
bookRoom
method is overloaded with two different signatures. One accepts a single integer to book for a single person, and the other accepts an integer for the number of people and a string for special requests. - Compile-time polymorphism determines which method to call based on the number of arguments during the compilation.
2. Runtime Polymorphism (Method Overriding)
Real-Life Scenario: Imagine you are designing a vehicle rental system. The Vehicle
class could have a start()
method, but different types of vehicles (like Car
, Bike
, Truck
) may start in different ways.
- The
Vehicle
class has a generalstart()
method. - The
Car
,Bike
, andTruck
subclasses each override thestart()
method to provide their own specific implementation.
This is a real-life scenario where different objects (vehicles) start in different ways, but we treat them generically as a Vehicle
in the system.
javaCopyclass Vehicle {
// Method in superclass
public void start() {
System.out.println("Starting the vehicle.");
}
}
class Car extends Vehicle {
// Overridden method in Car subclass
@Override
public void start() {
System.out.println("Starting the car with key ignition.");
}
}
class Bike extends Vehicle {
// Overridden method in Bike subclass
@Override
public void start() {
System.out.println("Starting the bike with a kick.");
}
}
class Truck extends Vehicle {
// Overridden method in Truck subclass
@Override
public void start() {
System.out.println("Starting the truck with a button.");
}
}
public class Main {
public static void main(String[] args) {
Vehicle vehicle1 = new Car();
Vehicle vehicle2 = new Bike();
Vehicle vehicle3 = new Truck();
// Calling the overridden start() method based on the actual object type
vehicle1.start(); // Output: Starting the car with key ignition.
vehicle2.start(); // Output: Starting the bike with a kick.
vehicle3.start(); // Output: Starting the truck with a button.
}
}
Explanation:
- In this example, we have method overriding where each subclass (
Car
,Bike
,Truck
) provides its own implementation of thestart()
method. - Runtime polymorphism happens when the program decides which
start()
method to call based on the actual object type, not the reference type (Vehicle
).- If a
Vehicle
reference points to aCar
, thestart()
method in theCar
class is called. - This decision happens at runtime, making it a runtime polymorphism example.
- If a
FAQs
1. What is the difference between method overloading and method overriding in Java?
- Method Overloading occurs at compile-time, where a method with the same name is defined but with different parameters (either number or type).
- Method Overriding occurs at runtime, where a subclass provides a specific implementation of a method that is already defined in its superclass.
2. Can we achieve polymorphism without inheritance in Java?
- No, polymorphism in Java is closely tied to inheritance. In order to use polymorphism, you need a superclass and one or more subclasses, where the method in the superclass is overridden by the subclasses.
3. How do you determine which method is called during runtime in method overriding?
- The method that gets called at runtime is determined by the type of the object, not the reference variable type. This is why it is called runtime polymorphism. For example, if a reference of type
Animal
points to aDog
object, theDog
‘s overridden method is called.
4. Is polymorphism possible in static methods?
- No, polymorphism does not apply to static methods because static methods are resolved at compile time based on the reference type, not the object type. Static methods cannot be overridden; they are hidden in the subclass.
5. Can polymorphism improve the performance of Java applications?
- While polymorphism is essential for flexibility and code maintainability, it doesn’t directly impact performance. However, its use can lead to better-structured and more optimized code in the long run, as it promotes reusability and scalability.
6. Can we override a private or static method in Java?
- No, private methods cannot be overridden because they are not visible to subclasses. Similarly, static methods cannot be overridden; they can be hidden by redefining them in the subclass, but they are not polymorphic in nature.
7. What is dynamic method dispatch in Java?
- Dynamic method dispatch refers to the process by which Java decides at runtime which version of an overridden method to call. This decision is based on the actual object type, not the reference variable type, and is a key feature of runtime polymorphism.
8. Can we achieve polymorphism using interfaces in Java?
- Yes, polymorphism can be achieved using interfaces. Classes that implement the same interface can provide different implementations of the methods declared in the interface, allowing polymorphic behavior.
9. What is the role of super
in method overriding?
- The
super
keyword is used to call methods from the superclass. In the case of method overriding, you can usesuper
to call the overridden method in the superclass from the subclass, especially if you need to extend the functionality of the superclass method.
10. What happens if a subclass does not override a method in Java?
- If a subclass does not override a method from its superclass, the subclass inherits the method from the superclass. The superclass’s method will be invoked when the method is called on an object of the subclass.
11. Can polymorphism be used with constructors in Java?
- No, polymorphism cannot be applied to constructors because constructors are not inherited by subclasses. While a subclass can have its own constructor, it cannot override the constructor of its superclass.
12. Can polymorphism be used with final methods in Java?
- No, polymorphism cannot be applied to
final
methods. Thefinal
keyword prevents a method from being overridden in a subclass, meaning the method is resolved at compile time and is not subject to polymorphism.
Learn about Creating Objects with “new” keyword vs. Using Factory Methods in Java