Inheritance
BeginnerUse extends to build class hierarchies, override methods with @Override, call parent behaviour with super, and know when to prefer composition.
Overview
Inheritance lets a child class reuse and extend the behaviour of a parent class. Java supports single class inheritance (one extends) but multiple interface implementation. The @Override annotation is your safety net — the compiler verifies the method signature matches. super calls the parent's constructor or method. Every Java class implicitly extends Object, giving every object toString(), equals(), hashCode(), and wait/notify for threading. The composition-over-inheritance principle says: prefer has-a relationships over is-a when the relationship isn't truly hierarchical.
extends, @Override & super
The child class inherits all non-private members of the parent. Overriding replaces the parent's method with a new implementation — the method signature must match exactly (use @Override to get a compile error if it doesn't).
super.methodName() calls the parent's version of a method. super() in a constructor calls the parent constructor and must be the first statement. If you don't write super(), the compiler inserts super() automatically — so the parent must have a no-arg constructor.
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public String speak() {
return name + " makes a sound";
}
public String describe() {
return "I am " + name;
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // must call parent constructor first
this.breed = breed;
}
@Override // compiler verifies signature matches
public String speak() {
return name + " barks!";
}
@Override
public String describe() {
return super.describe() + ", a " + breed; // reuse + extend
}
public static void main(String[] args) {
Dog dog = new Dog("Rex", "Labrador");
System.out.println(dog.speak()); // Rex barks!
System.out.println(dog.describe()); // I am Rex, a Labrador
// Polymorphic reference — Animal variable holds a Dog
Animal a = new Dog("Buddy", "Poodle");
System.out.println(a.speak()); // Buddy barks! (runtime dispatch)
System.out.println(a instanceof Dog); // true
}
}The Object Class & Covariant Return Types
Object is the root of every Java class hierarchy. Key methods inherited by all objects:
toString() — called implicitly by println and string concatenation equals(Object) + hashCode() — must be overridden together getClass() — returns the runtime Class object clone() — protected; implement Cloneable to expose finalize() — deprecated; don't rely on it wait() / notify() / notifyAll() — low-level thread synchronisation
Covariant return type: an overriding method may return a more specific type than the parent declared. This is useful for builder patterns and factory methods.
public class Shape {
public Shape copy() {
return new Shape(); // returns Shape
}
@Override
public String toString() { return "Shape"; }
}
public class Circle extends Shape {
private double radius;
public Circle(double r) { this.radius = r; }
// Covariant return — Circle is more specific than Shape
@Override
public Circle copy() {
return new Circle(radius); // allowed in Java
}
@Override
public String toString() { return "Circle(r=" + radius + ")"; }
public static void main(String[] args) {
Circle c = new Circle(5.0);
Circle c2 = c.copy(); // no cast needed — covariant return
System.out.println(c2); // Circle(r=5.0)
// getClass() and instanceof
System.out.println(c.getClass().getSimpleName()); // Circle
System.out.println(c instanceof Shape); // true
System.out.println(c instanceof Circle); // true
}
}Composition vs Inheritance
Inheritance models an IS-A relationship: a Dog IS-A Animal. Composition models a HAS-A relationship: a Car HAS-A Engine. Prefer composition when:
• The relationship is not truly hierarchical • You want to reuse behaviour from multiple sources (Java only allows one superclass) • You want to change the implementation at runtime (strategy pattern) • The subclass breaks the Liskov Substitution Principle (callers cannot safely substitute the subclass for the parent)
Favour composition over inheritance is one of the core principles of the Gang of Four design patterns book.
// Inheritance — tight coupling, fragile
class ElectricCar extends Battery { } // BAD: Car IS-A Battery? No.
// Composition — flexible, correct
public class Engine {
public void start() { System.out.println("Engine started"); }
}
public class GPS {
public String getLocation() { return "37.7749° N, 122.4194° W"; }
}
public class Car {
private final Engine engine = new Engine(); // HAS-A Engine
private final GPS gps = new GPS(); // HAS-A GPS
public void drive() {
engine.start();
System.out.println("Driving to " + gps.getLocation());
}
}
// Real-world composition example: Stack built on top of Deque
import java.util.ArrayDeque;
import java.util.Deque;
public class Stack<T> {
private final Deque<T> deque = new ArrayDeque<>(); // composed, not extended
public void push(T item) { deque.push(item); }
public T pop() { return deque.pop(); }
public T peek() { return deque.peek(); }
public boolean isEmpty() { return deque.isEmpty(); }
}Interactive Visualization
Key Points to Remember
- Java supports single inheritance for classes; use interfaces for multiple type inheritance
- @Override makes the compiler verify the signature — always use it when overriding
- super() to call parent constructor must be the first line; compiler inserts it if missing
- Method dispatch is decided at runtime based on the actual object type (dynamic dispatch)
- Covariant return types let overriding methods return a more specific type
- Prefer composition over inheritance when the IS-A relationship is not genuine
Practice Inheritance in the Playground
Run and modify code directly in your browser - no setup needed.
Interview Questions
Sign in to ask AriaWhat is the difference between method overloading and method overriding?
Can you override a private method in Java?
What is the Liskov Substitution Principle? Give an example of a violation.
Why does Java not support multiple inheritance for classes?
When would you choose composition over inheritance?
Ask Aria about Inheritance
Your personal AI tutor — ask anything about this concept