Composition
- In Turkish
- Bileşim
- Pronunciation
- kom-puh-ZISH-un
In short
Composition builds an object out of other objects that it holds and delegates work to, modeling a has-a relationship instead of inheriting from a parent class.
What is composition in programming?
Composition means building a class from other objects instead of extending a parent class. A Car doesn't inherit from Engine; it has an engine, kept in a field, and its start() method simply asks that engine to start. Passing work on to an object you hold like this is called delegation, and the relationship is described as has-a: a car has an engine, a page has a header, an order has line items.
Because the parts are ordinary objects, usually behind interfaces, they can be swapped. A car can get an electric engine instead of a petrol one when it is built, or even while the program runs, and a test can hand in a fake engine. The strategy, decorator and dependency injection patterns are all built on this idea. It is like building with LEGO bricks instead of carving a statue from one block: every part stays separate and replaceable.
"Favor object composition over class inheritance" is a principle from the 1994 book Design Patterns by the authors known as the Gang of Four. Inheritance ties a subclass to its parent's internals, so a change in the parent can break every child, and hierarchies multiply when features combine: ElectricCar, HybridCar, SelfDrivingElectricCar. Some languages lean on composition by design: Go has no class inheritance and embeds one struct in another instead, and Kotlin can delegate a whole interface to a field with the by keyword.
Composition is mostly weighed against inheritance, and the test is the relationship. Use inheritance when one type truly is a kind of another, as a Dog is an Animal, and composition when it has or uses something. Composition costs a little more code, since each delegating method has to be written, but the result is easier to change. The word has two other meanings as well: in UML diagrams, composition is a strong ownership where the parts live and die with the whole, and in functional programming, function composition chains functions so the output of one feeds the next.
Key takeaways
- Composition builds an object from other objects that it holds and delegates to.
- It models a has-a relationship, while inheritance models an is-a relationship.
- Parts behind interfaces can be swapped, which keeps code flexible and easy to test.
- "Composition over inheritance" means reaching for composition first when reusing behavior.
- Go and Kotlin support it directly, through struct embedding and the
bykeyword.
Example
interface Engine { start(): string; }
class PetrolEngine implements Engine { start() { return "vroom"; } }
class ElectricEngine implements Engine { start() { return "hum"; } }
// A Car HAS an engine and delegates to it, so there is no need for
// PetrolCar, ElectricCar and HybridCar subclasses
class Car {
constructor(private engine: Engine) {}
start() { return `Car starting: ${this.engine.start()}`; }
}
new Car(new ElectricEngine()).start(); // "Car starting: hum"Readers ask
What does "composition over inheritance" mean?
It is a design guideline: to reuse behavior, prefer holding an object that provides it over extending a class that has it. Inheritance isn't forbidden; it is kept for true is-a relationships.
What is the difference between composition and aggregation?
Both are has-a relationships. In UML, composition means the whole owns its parts and they are destroyed with it, like a house and its rooms, while aggregation means the parts can exist on their own, like a team and its players. In everyday code, the word composition usually covers both.
How does composition make testing easier?
The parts usually arrive from outside, often through the constructor, so a test can pass in a stub or a fake, such as an in-memory database instead of the real one, without changing the class itself.
See also
- InheritanceProgramming Fundamentals, p. 33Inheritance is an object-oriented programming feature that lets a new class reuse, extend, and override the fields and methods of an existing class.
- InterfaceProgramming Fundamentals, p. 34An interface is a named set of method and property signatures that a type promises to provide, without saying how those members are implemented.
- OOPProgramming Fundamentals, p. 46OOP, or object-oriented programming, is a way of structuring code around objects that bundle related data together with the functions that act on that data.
- Dependency InjectionSoftware Architecture, p. 13Dependency injection is a design technique in which an object receives the other objects it needs from the outside instead of creating them itself.
- Strategy PatternSoftware Architecture, p. 46The strategy pattern is a behavioral design pattern that puts interchangeable algorithms behind one interface, so code can switch between them at run time.
- Decorator PatternSoftware Architecture, p. 12The decorator pattern adds behavior like logging or caching to an object by wrapping it in another with the same interface, without changing the original.
Sources
Spotted a mistake or something missing on this page?Suggest an edit