On this page
In object-oriented programming (OOP), the mantra "favor composition over inheritance" is a fundamental principle for building maintainable and scalable systems. While inheritance is often the first concept taught in C#, it can lead to rigid, fragile codebases if overused.
The Core Difference
- Inheritance represents an "is-a" relationship. A
Dogis-aAnimal. It creates a tight coupling between the base class and the subclass. - Composition represents a "has-a" relationship. A
Carhas-anEngine. It allows you to build complex functionality by combining smaller, independent objects.
The Bad Example: The Fragile Inheritance Chain
Using inheritance to share behavior often leads to the "Lollipop" problem or deep hierarchies that are hard to change. If you want a RobotDog that barks but doesn't eat, a standard inheritance tree breaks.
Why this is bad:
- Breaking LSP: The
RobotDogviolates the Liskov Substitution Principle by throwing an exception for a base class method. - Tight Coupling: Any change in the
Animalclass ripples down to every subclass, potentially breaking unexpected things.
The Good Example: Flexible Composition
Instead of forcing a hierarchy, we define behaviors as interfaces or independent classes and "compose" our objects using them.
Why this is better:
- Runtime Flexibility: You can change an object's behavior at runtime by swapping the internal component.
- Single Responsibility: Each class does one thing well (e.g.,
SimpleBarkeronly handles barking). - Easier Testing: You can easily mock
IBarkerto test theDogclass in isolation.