codingstuff.io
ExploreTutorialsProblemsCS Subjects
Get Started
ExploreTutorialsProblemsCS Subjects
Get Started
codingstuff.io

Master the art of building software through interactive tutorials, real-world problems, and guided projects.

Pune, Maharashtra, India

codingstuffmail@gmail.com

Product

  • Explore
  • Tutorials
  • Problems
  • CS Subjects

Company

  • About
  • Contact
  • Privacy Policy
  • Terms & Conditions
  • Sitemap

Ā© 2026 codingstuff.io. All rights reserved.

Built with ā¤ļø for developers everywhere

/
/
All Subjects
🧩

OOP Concepts

23 chapters

1Procedural vs Object-Oriented2Classes, Objects, & Instantiation3Constructors & Destructors4Static Members & Methods5Encapsulation & Access Modifiers6Data Abstraction7Inheritance Types (Single, Multiple)8Compile-Time Polymorphism (Overloading)9Polymorphism & Interfaces10Run-Time Polymorphism (Overriding)11Virtual Functions & V-Tables12Interfaces & Abstract Classes13Generic Programming (Templates & Generics)14Exception Handling in OOP15SOLID Design Principles16Composition over Inheritance17Coupling & Cohesion18UML Diagrams Basics19Creational Patterns (Singleton, Factory)20Structural Patterns (Adapter, Decorator)21Behavioral Patterns (Observer, Strategy)22MVC Architecture Pattern23Object Serialization & Cloning
SubjectsOOP Concepts

Composition over Inheritance

Updated 2026-05-04
2 min read

Composition over Inheritance

While Inheritance is a powerful tool, overusing it creates deep, rigid class hierarchies that are difficult to modify and test. The principle of "Favor Composition over Inheritance" (from the Gang of Four's Design Patterns book, 1994) suggests that you should build complex behavior by combining simple, independent objects rather than by creating deep inheritance trees.

1. The Problem with Deep Inheritance

Imagine you are building a game and need various character types. You start with inheritance:

Character
ā”œā”€ā”€ Warrior (can fight)
ā”œā”€ā”€ Archer (can shoot)
ā”œā”€ā”€ Mage (can cast spells)

This works initially. But then requirements change:

  • You need a Paladin that can fight AND cast spells.
  • You need a Ranger that can shoot AND fight.

With single inheritance (Java), Paladin cannot extend both Warrior AND Mage. You're stuck. You either duplicate code or create an increasingly tangled hierarchy.

This is known as the Fragile Base Class Problem. Changes to a parent class can have unintended cascading effects on dozens of child classes deep in the hierarchy.

2. Composition: The Solution

Instead of defining abilities through an inheritance chain, you define abilities as independent, self-contained objects and compose them into a character.

// Independent ability components
class FightAbility {
    void fight() { System.out.println("Swinging sword!"); }
}

class ShootAbility {
    void shoot() { System.out.println("Firing arrow!"); }
}

class MagicAbility {
    void castSpell() { System.out.println("Casting fireball!"); }
}

// Characters are COMPOSED of abilities
class Paladin {
    private FightAbility fighter = new FightAbility();
    private MagicAbility mage = new MagicAbility();

    void fight() { fighter.fight(); }
    void castSpell() { mage.castSpell(); }
}

class Ranger {
    private FightAbility fighter = new FightAbility();
    private ShootAbility archer = new ShootAbility();

    void fight() { fighter.fight(); }
    void shoot() { archer.shoot(); }
}

Now, adding a new character type (DarkKnight that fights and casts spells) requires zero modification of existing code. You just compose the existing ability objects in a new configuration.

3. HAS-A vs. IS-A

The key mental model:

  • Inheritance models "IS-A": A Dog IS-A Animal. This is a permanent, defining identity.
  • Composition models "HAS-A": A Car HAS-A Engine. A Paladin HAS-A FightAbility. These are interchangeable components.

Use IS-A when the relationship is truly definitional and permanent. Use HAS-A when the relationship is about capability, configuration, or behavior that might change.

4. Dependency Injection

Composition is most powerful when combined with Dependency Injection (DI). Instead of the Paladin class internally creating its own FightAbility object (tight coupling), the ability is injected from the outside:

class Paladin {
    private FightAbility fighter;
    private MagicAbility mage;

    // Dependencies are INJECTED via the constructor
    Paladin(FightAbility fighter, MagicAbility mage) {
        this.fighter = fighter;
        this.mage = mage;
    }
}

This makes the Paladin class incredibly easy to test. In a unit test, you can inject a MockFightAbility that records calls instead of actually fighting, making assertions trivial.



PreviousSOLID Design PrinciplesNextCoupling & Cohesion

Recommended Gear

SOLID Design PrinciplesCoupling & Cohesion