Types of Inheritance
Inheritance lets one class acquire the fields and methods of another, encouraging code reuse and a natural “is-a” relationship. Java supports five conceptual types of inheritance, though it enforces one important restriction: a class can extend only one class at a time. Understanding each type helps you design cleaner, more maintainable class hierarchies.
1. Single Inheritance
The simplest form — one child class extends exactly one parent class. The child inherits everything that is accessible (non-private) from the parent.
class Animal {
void breathe() {
System.out.println("Breathing...");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Woof!");
}
}
public class Main {
public static void main(String[] args) {
Dog d = new Dog();
d.breathe(); // inherited from Animal
d.bark(); // Dog's own method
}
}
Output:
Breathing...
Woof!
Single inheritance is what you’ll use 80 % of the time. It keeps the hierarchy shallow and easy to reason about.
2. Multilevel Inheritance
A chain of inheritance — class B extends A, and class C extends B. C indirectly inherits from A through B.
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}
class Car extends Vehicle {
void drive() {
System.out.println("Car is driving");
}
}
class ElectricCar extends Car {
void charge() {
System.out.println("Charging battery...");
}
}
public class Main {
public static void main(String[] args) {
ElectricCar ec = new ElectricCar();
ec.start(); // from Vehicle
ec.drive(); // from Car
ec.charge(); // from ElectricCar
}
}
Output:
Vehicle started
Car is driving
Charging battery...
Tip: Keep your chains short (2–3 levels). Deep hierarchies become hard to follow and test — a smell that composition might be a better fit.
3. Hierarchical Inheritance
One parent class is extended by multiple child classes. Each child independently inherits the parent’s members.
class Shape {
void draw() {
System.out.println("Drawing a shape");
}
}
class Circle extends Shape {
void drawCircle() {
System.out.println("Drawing a circle");
}
}
class Rectangle extends Shape {
void drawRectangle() {
System.out.println("Drawing a rectangle");
}
}
public class Main {
public static void main(String[] args) {
Circle c = new Circle();
c.draw(); // inherited
c.drawCircle();
Rectangle r = new Rectangle();
r.draw(); // same inherited method
r.drawRectangle();
}
}
Output:
Drawing a shape
Drawing a circle
Drawing a shape
Drawing a rectangle
This is the classic “template + specialization” pattern. Shape defines common behavior; each subclass adds its own unique drawing logic.
4. Multiple Inheritance (via Interfaces)
Multiple inheritance means a class inherits from more than one parent. Java does not allow a class to extend multiple classes directly — this avoids the infamous Diamond Problem (see below). However, a class can implement multiple interfaces, which achieves the same goal safely.
interface Flyable {
default void fly() {
System.out.println("Flying...");
}
}
interface Swimmable {
default void swim() {
System.out.println("Swimming...");
}
}
class Duck implements Flyable, Swimmable {
void quack() {
System.out.println("Quack!");
}
}
public class Main {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // from Flyable
duck.swim(); // from Swimmable
duck.quack(); // Duck's own
}
}
Output:
Flying...
Swimming...
Quack!
Note:
defaultmethods in interfaces were introduced in Java 8. If two interfaces provide adefaultmethod with the same signature, the implementing class must override it to resolve the ambiguity — the compiler will refuse to compile otherwise.
The Diamond Problem
If Java allowed class C extends A, B and both A and B inherited from a common ancestor X with a method greet(), C would have two copies of greet() and the JVM wouldn’t know which to call. Java sidesteps this entirely by forbidding multi-class inheritance. Interfaces with default methods face the same conflict, but the compiler forces you to resolve it explicitly.
interface A {
default void greet() { System.out.println("Hello from A"); }
}
interface B {
default void greet() { System.out.println("Hello from B"); }
}
// Must override greet() or the compiler reports an error
class C implements A, B {
@Override
public void greet() {
A.super.greet(); // explicitly pick A's version
System.out.println("Hello from C");
}
}
5. Hybrid Inheritance
Hybrid inheritance is a combination of two or more types (e.g., hierarchical + multiple). Because Java forbids multiple class inheritance, hybrid inheritance involving multiple parents is achieved through interfaces.
interface Printable {
void print();
}
interface Saveable {
void save();
}
class Document {
void open() {
System.out.println("Document opened");
}
}
// Hierarchical (Document → PDFDocument) +
// Multiple interface (Printable + Saveable)
class PDFDocument extends Document implements Printable, Saveable {
@Override
public void print() {
System.out.println("Printing PDF...");
}
@Override
public void save() {
System.out.println("Saving PDF...");
}
}
public class Main {
public static void main(String[] args) {
PDFDocument pdf = new PDFDocument();
pdf.open();
pdf.print();
pdf.save();
}
}
Output:
Document opened
Printing PDF...
Saving PDF...
Quick Comparison
| Type | Relationship | Supported via |
|---|---|---|
| Single | A → B | extends |
| Multilevel | A → B → C | extends (chain) |
| Hierarchical | A → B, A → C | extends (multiple children) |
| Multiple | A + B → C | implements (interfaces only) |
| Hybrid | Mix of above | extends + implements |
Under the Hood
Constructor Chaining Across the Hierarchy
Whenever you instantiate a class, the JVM calls constructors from the top of the chain down. Every constructor implicitly calls super() as its first statement unless you write one yourself. For a chain Vehicle → Car → ElectricCar, creating an ElectricCar triggers three constructors in order: Vehicle(), Car(), then ElectricCar().
class Vehicle {
Vehicle() { System.out.println("Vehicle()"); }
}
class Car extends Vehicle {
Car() { System.out.println("Car()"); }
}
class ElectricCar extends Car {
ElectricCar() { System.out.println("ElectricCar()"); }
}
public class Main {
public static void main(String[] args) {
new ElectricCar();
}
}
Output:
Vehicle()
Car()
ElectricCar()
This guarantees that parent state is always initialized before child state.
Method Resolution & vtable
The JVM builds a virtual method table (vtable) for every class. When a subclass overrides a method, the vtable slot for that method is updated to point to the new implementation. At runtime, a virtual invokevirtual bytecode instruction looks up the correct slot for the actual object type — this is the engine behind runtime polymorphism. See vtable & Dynamic Dispatch for a deeper dive.
Memory Layout
The JVM lays out object memory with the parent’s fields first, followed by the child’s fields. This means instanceof checks and casts are fast (they just check a type pointer in the object header), regardless of how deep the hierarchy runs.
Warning: Keep class hierarchies shallow (typically no more than 3–4 levels). Deep chains increase coupling, make refactoring painful, and can confuse both humans and JIT optimizers.
Key Rules to Remember
- A class can
extendonly one class (single, multilevel, hierarchical). - A class can
implementmultiple interfaces (multiple, hybrid). - An interface can
extendmultiple interfaces — interface-to-interface inheritance has no diamond restriction. - Constructors are not inherited, but the parent constructor is called via
super(). - Private members are not inherited — they stay encapsulated in the declaring class.
- Use the
superkeyword to explicitly call a parent method or constructor.
Related Topics
- Inheritance — the core concept behind all five types covered here
- super Keyword — call parent constructors and methods across the hierarchy
- Interface — how Java achieves multiple and hybrid inheritance safely
- Runtime Polymorphism — how method overriding works across an inheritance chain
- Abstract Class — a partial implementation pattern that pairs naturally with inheritance
- Aggregation (HAS-A) — when inheritance is not the right tool and composition wins