Polymorphism is one of the core concepts of Object-Oriented Programming (OOP) in Java. It allows objects to take on multiple forms and enables a single method or class to have different implementations. Polymorphism in Java is primarily achieved through method overloading (compile-time polymorphism) and method overriding (runtime polymorphism).
1. Types of Polymorphism
a. Compile-Time Polymorphism (Method Overloading)
- Occurs when multiple methods in the same class have the same name but different parameters (different number or types of parameters).
- The method to be executed is determined at compile time based on the method signature.
b. Runtime Polymorphism (Method Overriding)
- Occurs when a subclass provides a specific implementation of a method that is already defined in its superclass.
- The method to be executed is determined at runtime based on the object being referred to.
2. Method Overloading (Compile-Time Polymorphism)
Key Points:
- Methods must have the same name but different parameter lists (number or types of parameters).
- Return type does not matter for overloading.
- Can occur within the same class or between a class and its subclass.
Example:
class Calculator {
// Method to add two integers
int add(int a, int b) {
return a + b;
}
// Overloaded method to add three integers
int add(int a, int b, int c) {
return a + b + c;
}
// Overloaded method to add two doubles
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 10)); // Calls first method
System.out.println(calc.add(5, 10, 15)); // Calls second method
System.out.println(calc.add(5.5, 10.5)); // Calls third method
}
}
3. Method Overriding (Runtime Polymorphism)
Key Points:
- The method in the subclass must have the same name, return type, and parameters as the method in the superclass.
- The
@Override
annotation is used to indicate that a method is being overridden (optional but recommended). - The method to be executed is determined at runtime based on the object being referred to (dynamic method dispatch).
Example:
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal(); // Animal object
Animal myDog = new Dog(); // Dog object (upcasting)
Animal myCat = new Cat(); // Cat object (upcasting)
myAnimal.sound(); // Calls Animal's sound method
myDog.sound(); // Calls Dog's sound method (runtime polymorphism)
myCat.sound(); // Calls Cat's sound method (runtime polymorphism)
}
}
4. Differences Between Method Overloading and Overriding
Feature | Method Overloading | Method Overriding |
---|---|---|
Definition | Multiple methods with the same name but different parameters in the same class. | Subclass provides a specific implementation of a method already defined in the superclass. |
Occurs In | Same class or between a class and its subclass. | Subclass and superclass. |
Parameter List | Must be different. | Must be the same. |
Return Type | Can be different. | Must be the same. |
Binding | Resolved at compile time. | Resolved at runtime. |
Purpose | Increases readability by using the same method name for similar tasks. | Provides specific implementation of a method in a subclass. |
Example | int add(int a, int b) and double add(double a, double b) . | void sound() in Animal and Dog . |
5. Rules for Method Overriding
- Same Signature: The method in the subclass must have the same name, return type, and parameters as the method in the superclass.
- Access Modifier: The access level cannot be more restrictive than the overridden method (e.g., cannot override a
public
method asprivate
). - Final Methods: Cannot override a
final
method. - Static Methods: Cannot override a
static
method (method hiding occurs instead). - Private Methods: Cannot override a
private
method (not visible in the subclass).
6. Example Program Combining Overloading and Overriding
class Shape {
// Method Overloading
void draw() {
System.out.println("Drawing a shape");
}
void draw(String color) {
System.out.println("Drawing a shape with color: " + color);
}
}
class Circle extends Shape {
// Method Overriding
@Override
void draw() {
System.out.println("Drawing a circle");
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Shape();
shape.draw(); // Calls Shape's draw method
shape.draw("Red"); // Calls overloaded draw method
Circle circle = new Circle();
circle.draw(); // Calls Circle's overridden draw method
}
}
7. Advantages of Polymorphism
- Code Reusability: Reuse methods and classes in different contexts.
- Flexibility: Allows objects to behave differently based on their runtime type.
- Extensibility: Easily extend functionality by adding new subclasses.
- Simplified Code: Improves readability and maintainability by using a single interface for multiple forms.
Summary
Concept | Description |
---|---|
Method Overloading | Multiple methods with the same name but different parameters. |
Method Overriding | Subclass provides a specific implementation of a superclass method. |
Compile-Time Polymorphism | Achieved through method overloading. |
Runtime Polymorphism | Achieved through method overriding. |
Rules for Overriding | Same signature, access modifier, and no overriding of final /static methods. |
Polymorphism is a powerful feature of Java that enables flexibility and extensibility in object-oriented programming. Understanding method overloading and overriding is essential for writing efficient and maintainable code.