Dataslope logoDataslope

Composition

The "has-a" relationship — building rich objects out of smaller ones, and why composition is the most important relationship in OOP

A complete object model is never one giant class. It is a graph of small classes that hold references to each other. The most common — and most important — relationship between two classes is composition: one class is made out of another.

A Car has an Engine. A House has Rooms. A Person has an Address. A Library has Books.

Every one of those sentences is a composition relationship in disguise.

The "has-a" relationship

Two classes can relate in many ways. The four we'll meet in this course are:

This page is about the strongest of them: composition. In a composition relationship, the whole owns the part. The part's lifetime is tied to the whole's. If the car goes to the junkyard, so does the engine.

In Java, composition looks like one class holding a private final field of another type, with the part being constructed by the whole (or handed in via the constructor) and never shared with anyone else.

A first example: Car has an Engine

The solid diamond *-- in UML means composition — strong ownership. The Engine is part of the Car.

Code Block
Java 8 (Update 492)

Things to notice:

  1. The Engine is created inside the Car. No outside code ever gets a reference to it.
  2. The Car's start, stop, and running methods delegate to the engine. The car does not implement engine logic itself — it asks the engine.
  3. When the Car becomes unreachable, the Engine becomes unreachable too. They live and die together.

Why composition matters

Composition is what lets you build big objects out of small ones. Each small one is well-encapsulated, easy to reason about, and easy to test. The big one just orchestrates.

If Library tried to do everything itself, it would be a 2000-line class. With composition, each concept gets its own small class with a focused job, and Library is mostly a coordinator.

Delegation: the partner of composition

A class that owns a part very often delegates part of its behavior to that part. Delegation just means "I'll ask the part to do this for me." It is the everyday verb of composition.

Code Block
Java 8 (Update 492)

Person.city() doesn't keep a city field. It asks its Address. If the rules for "what is your city" ever change, they change in one place — inside Address.

Composition is the answer to most modeling problems

Beginners often reach for inheritance ("a SportsCar extends Car") when composition would serve better ("a Car has an Engine, which might be a sports engine"). We will study inheritance later, and you will see how often the right move is to reach for composition first.

"Favor object composition over class inheritance" — Gang of Four

We're going to repeat that sentence several times this course. It is worth the repetition.

A richer example: a Computer composed of parts

This example shows multiple components combined into a whole, with each component encapsulated.

Code Block
Java 8 (Update 492)

Computer has zero logic of its own about CPUs, RAM, or SSDs. It delegates everything to the components and just assembles the answer. That is the goal: a containing class that orchestrates, with the real behavior living in well-defined parts.

Practice

Challenge
Java 8 (Update 492)
Compose a Book and an Author

Build a tiny model with two classes, Author and Book. A Book owns its Author.

  • Author has private final fields firstName and lastName and a method fullName() returning firstName + " " + lastName.
  • Book has private final fields title (String) and author (Author), and a method citation() returning title + " by " + author.fullName() — that is, Book delegates to Author.

The provided Main will print:

Pride and Prejudice by Jane Austen

Test your understanding

QuestionSelect one

Which of these is the clearest example of composition?

A Dog is a Mammal

A PrintService uses a Logger it was handed temporarily

A House has Rooms that are created and destroyed with the house

A Library keeps references to Books borrowed from a national archive

QuestionSelect one

When Car exposes start() and internally calls engine.ignite(), what is that pattern called?

Inheritance

Polymorphism

Delegation — the Car asks its part (the engine) to do the work

Abstraction leak

QuestionSelect one

Why is composition often preferred over inheritance when both are possible?

Composition is required by the Java compiler

Inheritance was deprecated in Java 17

Composition assembles small, swappable pieces, while inheritance locks classes into a rigid tree that's hard to change later

Composition methods always run faster

On this page