Low-Level Design Tutorial 0/42 lessons ~6 min read Lesson 8

    Inheritance

    Inheritance models is-a relationships: SavingsAccount is an Account, Truck is a Vehicle.

    Course progress0%
    Focus
    9 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Inheritance models is-a relationships: SavingsAccount is an Account, Truck is a Vehicle. Subclasses reuse and specialize superclass behavior — powerful but easy to misuse in LLD.

    Interviewers watch for fragile base classes, deep hierarchies, and violated Liskov substitution. Prefer shallow inheritance for true subtype relationships; use composition when behavior is shared but identity is not is-a.

    This lesson covers safe inheritance, method overriding, and when to stop subclassing.

    Understanding the topic

    Key concepts

    • extends for class inheritance; implements for interface implementation.
    • Superclass defines common state/behavior; subclass adds or overrides.
    • @Override methods must honor superclass contracts (LSP).
    • final prevents further subclassing when hierarchy should be closed.
    • Protected access shares with subclasses only — use sparingly.
    • Composition often replaces inheritance for code reuse without subtype coupling.

    Step-by-step explanation

    1. Confirm is-a relationship with substitution test: can subclass stand in for parent?
    2. Extract common fields/methods to superclass or interface default methods.
    3. Override methods preserving invariants and expectations.
    4. Use super.method() when extending, not replacing, behavior.
    5. Limit depth — two levels usually enough in interviews.
    6. Consider sealed class hierarchies for controlled extension.

    Informative example

    Vehicle hierarchy for parking lot — subtype-specific spot matching:

    java
    public abstract class Vehicle {
    private final String licensePlate;
    protected Vehicle(String licensePlate) {
    this.licensePlate = Objects.requireNonNull(licensePlate);
    }
    public String licensePlate() { return licensePlate; }
    public abstract SpotType requiredSpotType();
    }
    public final class Car extends Vehicle {
    public Car(String licensePlate) { super(licensePlate); }
    @Override
    public SpotType requiredSpotType() { return SpotType.COMPACT; }
    }
    public final class Truck extends Vehicle {
    public Truck(String licensePlate) { super(licensePlate); }
    @Override
    public SpotType requiredSpotType() { return SpotType.LARGE; }
    }
    public enum SpotType { COMPACT, LARGE }

    requiredSpotType() is the extension point — ParkingLot calls vehicle.requiredSpotType() without instanceof chains.

    Real-world use

    Real-world applications

    • Vehicle types, account types, chess piece movements.
    • Framework hooks (Template Method in servlet-style designs).
    • Sealed domain hierarchies with exhaustive handling.

    Best practices

    • Favor composition when relationship is has-a.
    • Keep superclass constructors simple and callable by subclasses.
    • Document what subclasses may override.
    • Avoid calling overridable methods from superclass constructor.
    • Use interfaces for roles; inheritance for shared implementation sparingly.

    Common mistakes

    • Inheritance for code reuse only (Wrong IS-A).
    • Breaking LSP — subclass throws where parent did not.
    • God superclass accumulating unrelated methods.
    • Deep trees (Animal → Mammal → Dog → …) hard to explain in interviews.

    Advanced interview questions

    Q1BeginnerWhen should you use inheritance?
    When a true is-a subtype relationship exists and substitution must work everywhere the parent is used.
    Q2BeginnerWhat does @Override do?
    Marks intentional method override; compiler catches signature mistakes.
    Q3IntermediateWhat is the Liskov Substitution Principle?
    Subtypes must be usable wherever their base type is expected without surprising behavior.
    Q4IntermediateInheritance vs interface implementation?
    Inheritance shares implementation and IS-A; interface implements CAN-DO roles without single inheritance limit issues.
    Q5AdvancedWhen would you use a sealed class hierarchy?
    Fixed set of variants (Shape, PaymentResult) needing exhaustive switches and controlled extension.

    Summary

    Use inheritance for genuine is-a relationships only. Override methods without breaking superclass contracts. Keep hierarchies shallow and domain-aligned. Prefer composition when reuse does not imply subtype. Sealed types control extension in Java 21.

    Ready to mark this lesson complete?Track your journey across the entire course.