All Courses
OOP: ANTI PATTERNS

Deep Inheritance

Concept Definition

Deep inheritance means a long chain of derived classes, such as A -> B -> C -> D -> E. Each level adds behavior or state, and the final class receives everything from the chain. This can make the object hard to understand.

Think of a rule book where every new page depends on five older footnotes. To understand one decision, you must read the whole history.

Why It Matters

Inheritance is powerful when the relationship is truly is-a. But deep inheritance often hides behavior across many files. A small change in a base class can unexpectedly affect every derived class.

Deep hierarchies are also hard to test. You may want to test the final class, but its behavior depends on several inherited layers. Composition is often clearer because it makes collaborators explicit.

Syntax Block

class Base {};
class Level1 : public Base {};
class Level2 : public Level1 {}; // possible deep hierarchy smell

Explained Code

Example: Prefer Composition for Features

#include <string> // std::string

class Logger {
public:
    void log(const std::string& message) { (void)message; } // reusable service
};

class ReportService {
private:
    Logger& logger;                         // explicit collaborator

public:
    explicit ReportService(Logger& serviceLogger) : logger(serviceLogger) {} // inject

    void generate() {
        logger.log("report generated");     // use service without inheriting it
    }
};

ReportService does not inherit from Logger. It has a logger because logging is a service, not an identity.

Key Points / Rules

  • Use inheritance for true substitutability.
  • Avoid inheritance only for code reuse.
  • Deep hierarchies hide behavior across many ancestors.
  • Composition makes collaborators visible.
  • Refactor when derived classes keep overriding inherited behavior to disable it.

Common Mistakes

  1. Treating has-a as is-a. A car has an engine; it is not an engine.
  2. Adding another derived class for every feature. Features often belong in composed services.
  3. Ignoring fragile base class changes. Base edits can break distant derived classes.
  4. Assuming inheritance is more OOP than composition. Good OOP uses both carefully.

Quick Check

  1. Why is deep inheritance hard to test?
  2. When is composition better than inheritance?

Viva Answer

Deep inheritance creates long fragile class chains. It should be avoided when behavior reuse can be expressed more clearly through composition.