DEV Community

Cover image for Inheritance: The Most Misused Pillar of OOP
Walter Nascimento
Walter Nascimento

Posted on • Edited on

Inheritance: The Most Misused Pillar of OOP

Inheritance was introduced to promote reuse.

But in modern systems,
it is one of the biggest sources of fragility.

Used correctly, it models specialization.

Used incorrectly, it creates tight coupling, broken abstractions, and subtle bugs.

Inheritance is powerful.

And dangerous.


A Brief Historical Context

Inheritance emerged strongly in Smalltalk and later C++ as a way to:

  • Reuse behavior
  • Model taxonomies
  • Represent “is-a” relationships

But as systems scaled, developers discovered something:

Inheritance couples classes more tightly than composition.

The child class is structurally bound to the parent.

If the parent changes, everything below it may break.


What Inheritance Really Means

Inheritance is:

  • A specialization relationship
  • A behavioral extension mechanism
  • A polymorphic substitution mechanism

Inheritance is not:

  • A code reuse shortcut
  • A way to share utilities
  • A dumping ground for common methods

If your only goal is reuse,
inheritance is often the wrong tool.


❌ The Wrong Way: Inheritance for Reuse

class FileLogger
{
    protected function format(string $message): string
    {
        return date('Y-m-d') . ' - ' . $message;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now someone wants email logging:

class EmailLogger extends FileLogger
{
    public function send(string $message): void
    {
        $formatted = $this->format($message);
        // send email
    }
}
Enter fullscreen mode Exit fullscreen mode

Why is this problematic?

  • EmailLogger depends on FileLogger
  • FileLogger was never meant to be a base abstraction
  • Shared logic forces structural coupling
  • Changing FileLogger impacts EmailLogger

This is inheritance for reuse.

And it's fragile.


The Rectangle / Square Problem

A classic example.

class Rectangle
{
    protected int $width;
    protected int $height;

    public function setWidth(int $width): void
    {
        $this->width = $width;
    }

    public function setHeight(int $height): void
    {
        $this->height = $height;
    }

    public function area(): int
    {
        return $this->width * $this->height;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now:

class Square extends Rectangle
{
    public function setWidth(int $width): void
    {
        $this->width = $width;
        $this->height = $width;
    }

    public function setHeight(int $height): void
    {
        $this->width = $height;
        $this->height = $height;
    }
}
Enter fullscreen mode Exit fullscreen mode

Seems logical.

But watch this:

function resize(Rectangle $rectangle): int
{
    $rectangle->setWidth(5);
    $rectangle->setHeight(10);

    return $rectangle->area();
}
Enter fullscreen mode Exit fullscreen mode

Expected result: 50.

If we pass Square?

Result: 100.

This violates the Liskov Substitution Principle.

The child cannot safely substitute the parent.

Inheritance broke behavioral expectations.


The Real Rule of Inheritance

For inheritance to be valid:

The child must fully respect the behavioral contract of the parent.

Not just the method signatures.

The behavior.

If overriding changes expectations,
inheritance is wrong.


When Inheritance Is Appropriate

Inheritance works well for:

  • Framework base classes (with strict contracts)
  • Template Method pattern
  • Controlled extensibility
  • Internal engine hierarchies

Example:

abstract class ReportGenerator
{
    public function generate(): void
    {
        $data = $this->collectData();
        $this->export($data);
    }

    abstract protected function collectData(): array;
    abstract protected function export(array $data): void;
}
Enter fullscreen mode Exit fullscreen mode

Concrete implementations specialize behavior without breaking the algorithm structure.

That’s safe inheritance.


Prefer Composition Over Inheritance

Instead of:

class EmailLogger extends FileLogger
Enter fullscreen mode Exit fullscreen mode

Use composition:

final class LoggerFormatter
{
    public function format(string $message): string
    {
        return date('Y-m-d') . ' - ' . $message;
    }
}
Enter fullscreen mode Exit fullscreen mode
final class EmailLogger
{
    public function __construct(
        private LoggerFormatter $formatter
    ) {}

    public function send(string $message): void
    {
        $formatted = $this->formatter->format($message);
        // send email
    }
}
Enter fullscreen mode Exit fullscreen mode

Now:

✔ No structural coupling
✔ Reuse without hierarchy
✔ Replaceable components
✔ Safer evolution

Composition isolates change.

Inheritance propagates change.


The Fragility Problem

Inheritance creates:

  • Tight coupling
  • Implicit dependencies
  • Hidden assumptions
  • Deep hierarchy complexity
  • Hard-to-reason systems

The deeper the hierarchy,
the harder the system becomes to maintain.

Modern architectures prefer shallow hierarchies and composition.


Advanced Insight: Inheritance and Encapsulation Conflict

Inheritance can weaken encapsulation.

Protected properties allow subclasses to manipulate internal state.

That breaks invariants.

That weakens object boundaries.

That introduces subtle bugs.

This is why many modern systems favor:

  • Final classes
  • Composition
  • Interfaces over abstract base classes

When NOT to Use Inheritance

Avoid inheritance when:

  • You only want code reuse
  • You cannot guarantee behavioral substitution
  • The base class wasn’t designed for extension
  • You foresee independent evolution

Final Insight

Inheritance is about specialization, not reuse.

If encapsulation protects internal state
and abstraction protects dependency boundaries

Inheritance must protect behavioral contracts.

Used correctly, it models true “is-a” relationships.

Used carelessly, it introduces silent architectural decay.

Inheritance is powerful.

That’s why it must be used carefully.


Thanks for reading!

If you have any questions, complaints or tips, you can leave them here in the comments. I will be happy to answer!
😊😊 See you! 😊😊


Support Me

Youtube - WalterNascimentoBarroso
Github - WalterNascimentoBarroso
Codepen - WalterNascimentoBarroso

Top comments (0)