Polymorphism is a fundamental concept in object-oriented programming (OOP) that
allows objects of different classes to be treated as objects of a common
superclass. In Java, polymorphism enables you to write more flexible and extensible
code by providing a way to perform different actions based on the actual type of an
object at runtime.
There are two main forms of polymorphism in Java: compile-time polymorphism (method
overloading) and runtime polymorphism (method overriding).
Compile-time Polymorphism (Method Overloading):
Method overloading allows you to define multiple methods with the same name but
different parameters within the same class. The compiler determines which method to
call based on the arguments passed during the method invocation. The methods must
have different parameter lists (i.e., different number or types of parameters) or
different return types.
Here's an example of method overloading:
java
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
}
In the example above, the Calculator class has two add methods, one that takes two
integers and another that takes two doubles. Depending on the argument types
passed, the appropriate add method will be invoked.
Runtime Polymorphism (Method Overriding):
Method overriding allows a subclass to provide its own implementation of a
method defined in its superclass. The method in the subclass must have the same
signature (name, return type, and parameters) as the method in the superclass.
Here's an example of method overriding:
java
public class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat meows");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
In the example above, the Animal class has a makeSound method, which is overridden
in both the Cat and Dog classes. When calling the makeSound method on an object of
type Animal, the appropriate implementation will be invoked based on the actual
type of the object at runtime.
Polymorphism is typically used in conjunction with inheritance to create more
flexible and reusable code. By treating objects of different classes as objects of
a common superclass, you can write code that operates on the superclass type,
making it easier to add new subclasses without modifying existing code.
For example:
java
Animal animal1 = new Cat();
Animal animal2 = new Dog();
animal1.makeSound(); // Output: "Cat meows"
animal2.makeSound(); // Output: "Dog barks"
In the above example, although the variables animal1 and animal2 are of type
Animal, they can hold objects of different subclasses (Cat and Dog). The
appropriate makeSound method is invoked based on the actual type of the objects
assigned to the variables.