We will learn the same concept in 3 levels:
LEVEL 1 → Basic Understanding
LEVEL 2 → Programming Understanding
LEVEL 3 → Deep / Interview Understanding
Using your Robo example throughout.
Inheritance is the process by which one class acquires the accessible properties and methods of another class.
In simple words:
Child class can reuse the functionality of Parent class.
Example:
Robo
|
┌───────┼────────┐
↓ ↓ ↓
Fighter Player Teacher
Robo is the Parent/Super class.
FighterRobo, PlayerRobo, and TeacherRobo are Child/Sub classes.
Suppose every Robo has:
move()
learn()
recharge()
interact()
Instead of writing these methods separately in every child class, we put them inside Robo.
Then:
Robo
├── move()
├── learn()
├── recharge()
└── interact()
Child classes can reuse them.
This gives:
Code Reusability
class Robo
{
public void move()
{
System.out.println("Robo moves fast");
}
public void learn()
{
System.out.println("Robo self learns");
}
public void recharge()
{
System.out.println("Plug in to recharge");
}
public void interact()
{
System.out.println("Robo interacts");
}
}
class FighterRobo extends Robo
{
public void fight()
{
System.out.println("Robo fights");
}
}
class PlayerRobo extends Robo
{
public void play()
{
System.out.println("Robo plays games");
}
}
class TeacherRobo extends Robo
{
public void teach()
{
System.out.println("Robo teaches");
}
}Diagram:
Robo
|
┌────────────┼────────────┐
↓ ↓ ↓
FighterRobo PlayerRobo TeacherRobo
| | |
fight() play() teach()
class FighterRobo extends RoboFighterRobo can use:
move() → inherited
learn() → inherited
recharge() → inherited
interact() → inherited
fight() → own method
So:
FighterRobo fr = new FighterRobo();
fr.move();
fr.learn();
fr.recharge();
fr.interact();
fr.fight();All are valid.
Because:
class FighterRobo extends Robowe can say:
FighterRobo IS-A Robo
Similarly:
PlayerRobo IS-A Robo
TeacherRobo IS-A Robo
This is called an:
IS-A relationship
Inheritance provides:
INHERITANCE
|
┌───────┼────────┐
↓ ↓ ↓
Reusability IS-A Specialization
Now let's understand how inheritance behaves in actual Java programs.
class Robo
{
public void move()
{
System.out.println("Robo moves fast");
}
public void learn()
{
System.out.println("Robo self learns");
}
public void recharge()
{
System.out.println("Plug in to recharge");
}
public void interact()
{
System.out.println("Robo interacts");
}
}
class FighterRobo extends Robo
{
public void fight()
{
System.out.println("Robo fights");
}
}
class PlayerRobo extends Robo
{
public void play()
{
System.out.println("Robo plays games");
}
}
class TeacherRobo extends Robo
{
public void teach()
{
System.out.println("Robo teaches");
}
}
class RoboApp
{
public static void main(String[] args)
{
FighterRobo fr = new FighterRobo();
System.out.println("Fighter Robo");
fr.move();
fr.learn();
fr.recharge();
fr.interact();
fr.fight();
System.out.println("----------------");
PlayerRobo pr = new PlayerRobo();
System.out.println("Player Robo");
pr.move();
pr.learn();
pr.recharge();
pr.interact();
pr.play();
System.out.println("----------------");
TeacherRobo tr = new TeacherRobo();
System.out.println("Teacher Robo");
tr.move();
tr.learn();
tr.recharge();
tr.interact();
tr.teach();
}
}Consider:
FighterRobo fr = new FighterRobo();The object can access:
FighterRobo
|
├── move()
├── learn()
├── recharge()
├── interact()
└── fight()
The first four methods come from Robo.
The last method comes from FighterRobo.
Therefore:
fr.move();calls the inherited Robo method.
And:
fr.fight();calls the FighterRobo method.
There are four important structures you need to remember.
One parent → One child.
Animal
↓
Dog
Program:
class Animal
{
public void eat()
{
System.out.println("Animal eats");
}
}
class Dog extends Animal
{
public void bark()
{
System.out.println("Dog barks");
}
}This is Single Inheritance.
One parent → Multiple children.
Robo
/ | \
↓ ↓ ↓
Fighter Player Teacher
Your complete Robo example is Hierarchical Inheritance.
Why?
Because:
Robo → FighterRobo
Robo → PlayerRobo
Robo → TeacherRobo
There is one parent and multiple child classes.
Grandparent → Parent → Child.
Animal
↓
Dog
↓
Puppy
Program:
class Animal
{
public void eat()
{
System.out.println("Animal eats");
}
}
class Dog extends Animal
{
public void bark()
{
System.out.println("Dog barks");
}
}
class Puppy extends Dog
{
public void play()
{
System.out.println("Puppy plays");
}
}Now:
Puppy p = new Puppy();
p.eat();
p.bark();
p.play();The Puppy object can access functionality from all three levels.
Puppy
↓
Dog
↓
Animal
Hybrid inheritance is a combination of different inheritance structures.
Your example:
Animal
/ | \
↓ ↓ ↓
Herbivores Carnivores Omnivores
↓ ↓ ↓
Cow Tiger Dog
There is a hierarchical structure:
Animal
/ | \
↓ ↓ ↓
Herbivores Carnivores Omnivores
And multilevel paths:
Animal
↓
Herbivores
↓
Cow
Therefore the overall structure is hybrid.
Multiple inheritance means:
A B
\ /
\ /
C
One child has multiple parent classes.
Java does not support multiple inheritance through classes.
The main reason is ambiguity such as the Diamond Problem.
Consider:
A
/ \
B C
\ /
D
Suppose A has:
show()and B and C both provide their own versions.
Then:
D d = new D();
d.show();creates the question:
Should Java execute:
B's show()
OR
C's show()?
This is the Diamond Problem.
Java avoids this type of ambiguity by not supporting multiple inheritance through classes.
Java can support multiple inheritance of type through interfaces, with rules for resolving conflicting default methods.
Cyclic inheritance means a class hierarchy forms a circle.
A
↓
B
↓
C
↓
A
This is not permitted.
Why?
Because there is no proper root parent.
Inheritance should form a hierarchy:
A
↓
B
↓
C
not:
A → B → C → A
Remember:
1. Inherited
2. Overridden
3. Specialized
Parent method is used by child without changing it.
class Robo
{
public void move()
{
System.out.println("Robo moves");
}
}
class FighterRobo extends Robo
{
}Here:
move() → Inherited
Child provides its own implementation of a parent method with the same signature.
class Robo
{
public void fight()
{
System.out.println("Robo fights");
}
}
class FighterRobo extends Robo
{
public void fight()
{
System.out.println("Fighter Robo fights strongly");
}
}Here:
fight() → Overridden
Child introduces a new method that the parent does not have.
class FighterRobo extends Robo
{
public void specialAttack()
{
System.out.println("Fighter Robo performs special attack");
}
}Here:
specialAttack() → Specialized
class Robo
{
public void move()
{
System.out.println("Robo moves");
}
public void fight()
{
System.out.println("Robo fights");
}
public void recharge()
{
System.out.println("Robo recharges");
}
}
class FighterRobo extends Robo
{
// Overridden method
public void fight()
{
System.out.println("Fighter Robo fights strongly");
}
// Specialized method
public void specialAttack()
{
System.out.println("Fighter Robo performs special attack");
}
}
class RoboApp
{
public static void main(String[] args)
{
FighterRobo fr = new FighterRobo();
fr.move();
fr.recharge();
fr.fight();
fr.specialAttack();
}
}Classification:
move()
↓
Inherited
recharge()
↓
Inherited
fight()
↓
Overridden
specialAttack()
↓
Specialized
Now let's handle the doubts that usually cause confusion.
Constructors are not inherited.
But when a child object is created, the parent constructor participates in object initialization.
Example:
class Robo
{
Robo()
{
System.out.println("Robo constructor");
}
}
class FighterRobo extends Robo
{
FighterRobo()
{
System.out.println("Fighter Robo constructor");
}
}When:
FighterRobo fr = new FighterRobo();output is:
Robo constructor
Fighter Robo constructor
Remember:
Parent constructor
↓
Child constructor
But:
Constructors are NOT inherited.
Consider:
class Robo
{
private int battery = 100;
}The child cannot directly access:
batterybecause it is private.
But the parent can provide a public method:
class Robo
{
private int battery = 100;
public void showBattery()
{
System.out.println(battery);
}
}Then:
class FighterRobo extends Robo
{
}can call:
FighterRobo fr = new FighterRobo();
fr.showBattery();So:
Private members are not directly accessible inside the child class.
| Modifier | Child access |
|---|---|
private |
❌ Direct access not allowed |
| default | ✅ Same package |
protected |
✅ Accessible subject to protected rules |
public |
✅ Accessible |
super is used to refer to the immediate parent class.
It can be used to:
1. Access parent variable
2. Call parent method
3. Call parent constructor
Example:
class Robo
{
public void move()
{
System.out.println("Robo moves");
}
}
class FighterRobo extends Robo
{
public void move()
{
super.move();
System.out.println("Fighter Robo moves");
}
}Output:
Robo moves
Fighter Robo moves
This is extremely important.
class Robo
{
public void move()
{
System.out.println("Robo moves");
}
}
class FighterRobo extends Robo
{
public void move()
{
System.out.println("Fighter Robo moves");
}
}Now:
Robo r = new FighterRobo();
r.move();Output:
Fighter Robo moves
Why?
Because:
Reference type → Robo
Actual object → FighterRobo
The overridden method belonging to the actual object is selected at runtime.
This is runtime polymorphism.
Robo r = new FighterRobo();This is called upcasting.
FighterRobo
↓
Robo
It is valid because:
FighterRobo IS-A Robo
Robo r = new FighterRobo();
FighterRobo fr = (FighterRobo) r;This is downcasting.
Robo
↓
FighterRobo
After downcasting:
fr.fight();can be accessed through the FighterRobo reference.
But an invalid downcast can cause:
ClassCastException
A final class cannot be inherited.
final class Robo
{
}This is not allowed:
class FighterRobo extends Robo
{
}because Robo is final.
A final method can be inherited but cannot be overridden.
class Robo
{
public final void move()
{
System.out.println("Robo moves");
}
}The child cannot redefine move().
Static methods belong to the class.
If a child declares a static method with the same signature as the parent, it is method hiding, not overriding.
class Robo
{
public static void show()
{
System.out.println("Robo");
}
}
class FighterRobo extends Robo
{
public static void show()
{
System.out.println("Fighter Robo");
}
}Remember:
Instance method → can be overridden
Static method → hidden, not overridden
Don't confuse:
IS-A
with:
HAS-A
FighterRobo IS-A Robo
Dog IS-A Animal
Car HAS-A Engine
House HAS-A Room
Inheritance
↓
Child acquires accessible functionality
↓
Parent
↓
Child
↓
Code Reusability
Robo
|
┌────────────┼────────────┐
↓ ↓ ↓
FighterRobo PlayerRobo TeacherRobo
| | |
fight() play() teach()
Common methods:
move()
learn()
recharge()
interact()
Child-specific methods:
fight()
play()
teach()
Therefore this is:
Hierarchical Inheritance
Inheritance
|
├── Code Reusability
├── IS-A Relationship
├── Method Overriding
├── Runtime Polymorphism
├── Upcasting
├── super
├── Constructor execution
├── Access modifiers
├── final restrictions
├── Static method hiding
├── Diamond Problem
└── Cyclic Inheritance
Inheritance means acquiring accessible functionality from a parent class.
Robo
|
├── FighterRobo
├── PlayerRobo
└── TeacherRobo
One parent + multiple children = Hierarchical Inheritance.
Remember these:
Inherited → Parent method reused
Overridden → Child changes implementation
Specialized → Child adds new method
Constructor → Not inherited
Private member → Not directly accessible in child
final class → Cannot be inherited
final method → Cannot be overridden
static method → Hidden, not overridden
A → B → C → Multilevel
A → B → Single
A → B,C,D → Hierarchical
Combination → Hybrid
Multiple classes → ❌ Not supported
Cyclic hierarchy → ❌ Not permitted
Inheritance allows a child class to reuse the accessible functionality of its parent, add its own specialized functionality, and override inherited methods when required.