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

    Composition vs Inheritance

    Composition builds objects by combining other objects (has-a).

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

    Introduction

    Composition builds objects by combining other objects (has-a). Inheritance specializes types (is-a). The Gang of Four advice — favor composition over inheritance — appears in nearly every LLD interview because composition reduces coupling and fragile base classes.

    Example: an Elevator has a Motor and Door, it is not a Motor. A Car is a Vehicle — inheritance fits. Choosing wrong damages extensibility.

    This lesson gives decision rules and refactoring paths when you inherit too eagerly.

    Understanding the topic

    Key concepts

    • Composition: delegate behavior to composed objects.
    • Inheritance: subtype polymorphism with shared interface.
    • Composition avoids exposing superclass internals.
    • Inheritance ties you to parent implementation changes.
    • Delegation pattern: outer object forwards calls to inner.
    • Mix: implement interface + compose helper (e.g., List decorator).
    text
    flowchart TB
    Encapsulation --> Abstraction
    Abstraction --> Inheritance
    Inheritance --> Polymorphism

    Step-by-step explanation

    1. Ask: is it truly a subtype? If no, compose.
    2. Identify behaviors to reuse — extract to separate class, inject.
    3. Expose composed object only through outer class methods.
    4. Use interface on outer class matching client needs.
    5. Replace inheritance with composition when subclass overrides most methods.
    6. Document owned lifecycle — outer creates/destroys components.

    Informative example

    Car composes Engine — does not extend Engine:

    java
    public final class Engine {
    public void start() { /* ... */ }
    public void stop() { /* ... */ }
    }
    public final class Car {
    private final Engine engine;
    private final String vin;
    public Car(String vin, Engine engine) {
    this.vin = vin;
    this.engine = engine;
    }
    public void startTrip() {
    engine.start();
    }
    public void endTrip() {
    engine.stop();
    }
    }

    If ElectricEngine and GasEngine differ, inject Engine interface implementations — Car stays stable.

    Real-world use

    Real-world applications

    • Replacing instanceof stacks with composed strategies.
    • Building rich domain objects from value components.
    • Testability — mock composed collaborators.

    Best practices

    • Default to composition for reuse of behavior.
    • Use inheritance when LSP-safe substitution is required.
    • Keep composed objects private.
    • Inject interfaces for composed parts.
    • Avoid multi-level inheritance; prefer flat composition trees.

    Common mistakes

    • Subclassing HashMap to add logging (fragile — use wrapper).
    • Inheriting utility class for random helper methods.
    • Exposing composed objects for direct mutation.
    • Deep inheritance where strategy object would suffice.

    Advanced interview questions

    Q1BeginnerWhat does 'favor composition over inheritance' mean?
    Reuse behavior by containing objects rather than subclassing unless IS-A is clear.
    Q2BeginnerGive an example of composition.
    A Car has an Engine; Car delegates start() to engine.start().
    Q3IntermediateWhen is inheritance still correct?
    True domain subtypes: SavingsAccount extends Account with substitutable behavior.
    Q4IntermediateHow does composition support testing?
    Inject mock collaborators without subclassing the system under test.
    Q5AdvancedRefactor inherited Stack with push logging to composition.
    Wrap Stack in LoggingStack delegating to inner Stack — no fragile extends Stack.

    Summary

    Composition = has-a; inheritance = is-a. Default to composition for behavior reuse. Inheritance when subtyping and LSP apply. Delegation keeps outer API stable. Composition simplifies testing and extension.

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