Java
Explain Inheritance, Method Overriding, and Polymorphism in Java with Real-World Analogy
By Utility Zone · 2025-11-06T10:11:53.28381
Java is fundamentally built on Object-Oriented Programming (OOP) principles. Three interconnected concepts—inheritance, method overriding, and polymorphism—work together to create flexible, reusable, and maintainable code. Understanding these concepts is crucial for effective Java development.

Relationship between inheritance, method overriding, and polymorphism in Java using an Animal class hierarchy
Inheritance
Inheritance is the mechanism by which one class (subclass or child class) acquires the properties and methods of another class (superclass or parent class). It promotes code reuse and establishes a hierarchical relationship between classes.123
Real-World Analogy: Family Inheritance
Think of inheritance like inheriting traits from your parents. Your parents (superclass) have certain characteristics and behaviors—height, eye color, intelligence—which they pass on to you (subclass). You inherit all their traits, but you can also develop your own unique characteristics while retaining what you inherited. Similarly, in Java, a child class inherits fields and methods from the parent class but can also add new properties and methods or modify inherited ones.4
Inheritance Syntax
class Subclass extends Superclass {
// Additional fields and methods
}
The extends keyword establishes the inheritance relationship.231
Single Inheritance Example
The most basic form where a class inherits from only one parent class:56
// Superclass (Parent)
class Animal {
void eat() {
System.out.println("Animal is eating");
}
}
// Subclass (Child) - Single Inheritance
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat(); // Inherited method from Animal
myDog.bark(); // Dog's own method
}
}
Output:
Animal is eating
Dog is barking
Types of Inheritance in Java
Java supports three main types of inheritance:567
1. Single Inheritance
2. Multilevel Inheritance
- A chain of inheritance where a child class becomes the parent of another class56
- Creates a hierarchy: Grandparent → Parent → Child
class Animal {
void eat() { System.out.println("Animal eats"); }
}
class Dog extends Animal {
void bark() { System.out.println("Dog barks"); }
}
class Labrador extends Dog {
void display() { System.out.println("Labrador is a type of Dog"); }
}
public class Main {
public static void main(String[] args) {
Labrador lab = new Labrador();
lab.eat(); // From Animal
lab.bark(); // From Dog
lab.display(); // From Labrador
}
}
Output:
Animal eats
Dog barks
Labrador is a type of Dog
3. Hierarchical Inheritance
- Multiple child classes inherit from a single parent class765
- Useful when several classes need common behaviors from one parent
class Animal {
void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Woof!"); }
}
class Cat extends Animal {
void meow() { System.out.println("Meow!"); }
}
class Bird extends Animal {
void chirp() { System.out.println("Chirp!"); }
}
Note: Java does not support multiple inheritance through classes (where a class inherits from multiple classes) because it leads to ambiguity. However, this can be achieved using interfaces.467
Method Overriding
Method overriding is the process where a subclass provides a specific implementation for a method that is already defined in its parent class. It allows you to redefine inherited methods with behavior specific to the child class.8
Rules for Method Overriding:8
- Method name must be the same as the parent class method
- Parameter list must be identical (same number, type, and order of parameters)
- Return type must be the same (or a compatible subtype)
- Cannot override static methods (static methods are class-level, not instance-level)
- Access modifier cannot be more restrictive (can be the same or less restrictive)
Method Overriding Example
// Parent Class
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
void eat() {
System.out.println("Animal is eating");
}
}
// Child Class 1
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks: Woof Woof!");
}
// eat() is inherited and not overridden
}
// Child Class 2
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows: Meow!");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // Output: Dog barks: Woof Woof!
dog.eat(); // Output: Animal is eating (inherited)
Cat cat = new Cat();
cat.sound(); // Output: Cat meows: Meow!
cat.eat(); // Output: Animal is eating (inherited)
}
}
Output:
Dog barks: Woof Woof!
Animal is eating
Cat meows: Meow!
Animal is eating
The @Override Annotation
The @Override annotation is a best practice that tells the compiler you intend to override a method. If you make a mistake (wrong method name, wrong parameters), the compiler will issue an error.9108
- Catches mistakes at compile time: If the method signature doesn't match, you get a compilation error
- Improves code readability: Makes it clear which methods are overridden
- Helps with refactoring: If you change a parent method signature, all subclasses will show compilation errors, ensuring you update them
class Animal {
void eat() { System.out.println("Animal eats"); }
}
class Dog extends Animal {
@Override // Compiler will check if this correctly overrides a parent method
void eat() { System.out.println("Dog eats meat"); }
}
Using the super Keyword
The super keyword allows you to call the parent class method from within the overridden method. This is useful when you want to extend the parent behavior rather than completely replace it:11
class Animal {
void eat() {
System.out.println("I can eat");
}
}
class Dog extends Animal {
@Override
void eat() {
super.eat(); // Call parent class method
System.out.println("I eat dog food");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
}
}
Output:
I can eat
I eat dog food
Polymorphism
Polymorphism means "many forms." In Java, it refers to the ability of objects to take multiple forms or for methods to be called in different ways. Polymorphism is achieved through inheritance and method overriding.121314
Real-World Analogy: Different Animals Making Sounds
Imagine you're at a zoo with a microphone. You announce, "All animals, make your sound!" Each animal responds in its own unique way: the dog barks, the cat meows, the bird chirps. Although they all received the same command (message), each animal responded differently based on its species (actual type). This is polymorphism—the same method call producing different behaviors based on the object type.1516
Two Types of Polymorphism
1. Compile-Time Polymorphism (Static Polymorphism)
This is resolved by the compiler during compilation through method overloading. The compiler determines which method to call based on the method signature (name, number, and type of parameters).1213
class Calculator {
// Method 1: Add two integers
int add(int a, int b) {
return a + b;
}
// Method 2: Add three integers
int add(int a, int b, int c) {
return a + b + c;
}
// Method 3: 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 Method 1
System.out.println(calc.add(5, 10, 15)); // Calls Method 2
System.out.println(calc.add(5.5, 10.5)); // Calls Method 3
}
}
Output:
15
30
16.0
2. Runtime Polymorphism (Dynamic Polymorphism)
This is resolved by the JVM at runtime through method overriding and upcasting. The actual object type determines which method is called, not the reference type.131417
Upcasting is treating a subclass object as an instance of its superclass. The reference type is the superclass, but the object is a subclass. At runtime, the JVM calls the appropriate method based on the actual object type.1817
Animal animal = new Dog(); // Upcasting: Dog object referenced by Animal type
animal.sound(); // Runtime decides to call Dog's sound() method
Runtime Polymorphism Example
// Parent Class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
// Child Class 1
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks: Woof!");
}
}
// Child Class 2
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows: Meow!");
}
}
// Child Class 3
class Bird extends Animal {
@Override
void makeSound() {
System.out.println("Bird chirps: Tweet!");
}
}
public class Main {
public static void main(String[] args) {
// Using parent class reference to hold different subclass objects
Animal animal;
animal = new Dog();
animal.makeSound(); // Output: Dog barks: Woof!
animal = new Cat();
animal.makeSound(); // Output: Cat meows: Meow!
animal = new Bird();
animal.makeSound(); // Output: Bird chirps: Tweet!
}
}
Output:
Dog barks: Woof!
Cat meows: Meow!
Bird chirps: Tweet!
Benefits of Runtime Polymorphism
// Real-world benefit: Writing flexible, reusable code
public void makeAnimalSound(Animal animal) {
animal.makeSound(); // Works with ANY subclass of Animal
}
public static void main(String[] args) {
makeAnimalSound(new Dog()); // Automatically calls Dog's makeSound()
makeAnimalSound(new Cat()); // Automatically calls Cat's makeSound()
makeAnimalSound(new Bird()); // Automatically calls Bird's makeSound()
}
This single method works with any current or future subclass of Animal without modification—this is the power of polymorphism.1314
Comprehensive Example: Complete Inheritance, Overriding, and Polymorphism
// Parent Class
public class Shape {
protected String color = "White";
public void display() {
System.out.println("Shape Color: " + color);
}
public void area() {
System.out.println("Calculating area...");
}
}
// Child Class 1
public class Circle extends Shape {
private double radius;
public Circle(double radius, String color) {
this.radius = radius;
this.color = color;
}
@Override
public void display() {
super.display(); // Call parent method
System.out.println("This is a Circle");
}
@Override
public void area() {
double circleArea = Math.PI * radius * radius;
System.out.println("Circle Area: " + circleArea);
}
}
// Child Class 2
public class Rectangle extends Shape {
private double length, width;
public Rectangle(double length, double width, String color) {
this.length = length;
this.width = width;
this.color = color;
}
@Override
public void display() {
super.display(); // Call parent method
System.out.println("This is a Rectangle");
}
@Override
public void area() {
double rectArea = length * width;
System.out.println("Rectangle Area: " + rectArea);
}
}
// Main Class
public class Main {
public static void main(String[] args) {
// Polymorphism: Parent reference, child objects
Shape shape1 = new Circle(5, "Red");
Shape shape2 = new Rectangle(4, 6, "Blue");
// Runtime polymorphism in action
shape1.display(); // Calls Circle's display()
shape1.area(); // Calls Circle's area()
System.out.println();
shape2.display(); // Calls Rectangle's display()
shape2.area(); // Calls Rectangle's area()
}
}
Output:
Shape Color: Red
This is a Circle
Circle Area: 78.53981633974483
Shape Color: Blue
This is a Rectangle
Rectangle Area: 24.0
Comparison: Inheritance vs Method Overriding vs Polymorphism
| Concept | Purpose | When Used | Example |
|---|---|---|---|
| Inheritance | Reuse code, establish hierarchy | Creating child classes from parents | Dog extends Animal |
| Method Overriding | Provide child-specific implementation | Modifying inherited methods | Dog overrides Animal.sound() |
| Polymorphism | Use one reference for multiple types | Flexible, reusable code | Animal ref = new Dog() |
Key Advantages
- Code Reusability: Write code once in parent class, use in all children1
- Maintainability: Changes in parent automatically propagate to children1
- Flexibility: Handle different types with single reference1314
- Extensibility: Add new subclasses without changing existing code13
- Reduced Redundancy: Avoid duplicate code across similar classes1
Together, inheritance, method overriding, and polymorphism form the backbone of object-oriented programming in Java, enabling developers to write clean, efficient, and scalable applications.11131 <span style="display:none">1920</span>
<div align="center">⁂</div>
Footnotes
-
https://unstop.com/blog/extends-keyword-in-java ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
https://www.w3schools.com/java/ref_keyword_extends.asp ↩ ↩2 ↩3
-
https://www.shiksha.com/online-courses/articles/types-of-inheritance-in-java-blogId-156091 ↩ ↩2
-
https://www.geekster.in/articles/java-inheritance/ ↩ ↩2 ↩3 ↩4
-
https://www.tutorialspoint.com/java/java_inheritance.htm ↩ ↩2 ↩3 ↩4 ↩5 ↩6
-
https://www.upgrad.com/blog/types-of-inheritance-in-java/ ↩ ↩2 ↩3 ↩4
-
https://www.geeksforgeeks.org/java/overriding-in-java/ ↩ ↩2 ↩3
-
https://beginnersbook.com/2014/07/override-annotation-in-java/ ↩ ↩2
-
https://www.geeksforgeeks.org/java/the-override-annotation-in-java/ ↩ ↩2
-
https://www.scholarhat.com/tutorial/java/java-polymorphism-compile-time-and-runtime ↩ ↩2
-
https://beginnersbook.com/2013/04/runtime-compile-time-polymorphism/ ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
https://www.geeksforgeeks.org/java/difference-between-compile-time-and-run-time-polymorphism-in-java/ ↩ ↩2 ↩3 ↩4
-
https://trainings.internshala.com/blog/polymorphism-in-java/ ↩
-
https://www.w3resource.com/java-exercises/java-polymorphism-exercise-1.php ↩
-
https://www.upgrad.com/blog/types-of-polymorphism-in-java/ ↩ ↩2 ↩3
-
https://dev.to/dhanush9952/upcasting-and-downcasting-in-java-an-overview-of-typecasting-3djl ↩ ↩2
-
https://www.w3resource.com/java-exercises/java-polymorphism-exercise-10.php ↩