OOP Concepts · Object Relationships

Association, Aggregation and Composition

Objects rarely live alone. A teacher teaches students, a department has teachers, a house owns its rooms. These three relationships — association, aggregation and composition — describe how strongly objects are tied.

Intermediate 6 min Lesson 19 of 38 Runnable examplesExamples use modern JavaScript (ES2022 private fields) and C# 13.
Before you start:Classes and Objects
0/38 in OOP Concepts
On this page · 6 min · Intermediate

In simple words#

A teacher and a student know each other (association). A class contains students who exist without it (aggregation). A house contains rooms that die with it (composition).

Association
Objects use each other.
Aggregation
“Has-a”, parts can live independently.
Composition
“Owns-a”, parts live and die with the whole.

Learning objectives#

  • Define association, aggregation and composition
  • Tell them apart by asking “who owns whom?”
  • Implement each in code
  • Recognise them in UML and interviews

Explanation#

Association (“uses-a”): two objects work together, but neither owns the other. A Teacher teaches a Student; both exist independently.

Aggregation (“has-a”, weak): one object contains others, but the parts can live on their own. A Department has Teachers; close the department and the teachers still exist.

Composition (“owns-a”, strong): the whole creates and owns its parts, and the parts die with it. A House owns its Rooms; a room without its house makes no sense.

Quick test: if the container is deleted, do the parts survive? Yes → aggregation. No → composition. No container at all → association.

In code: association and aggregation receive existing objects (through a constructor or method); composition usually creates its parts itself and keeps them private.

Syntax#

C# Illustrative
class Lesson(Teacher teacher, Student student) { }   // association: uses both


class Department                                       // aggregation: has teachers
{
    private readonly List<Teacher> _teachers = new();
    public void Add(Teacher t) => _teachers.Add(t);   // teachers created elsewhere
}


class House                                            // composition: owns rooms
{
    private readonly List<Room> _rooms;
    public House(params string[] names) => _rooms = names.Select(n => new Room(n)).ToList();
}

Code example: Teachers, departments and houses#

JavaScriptTeachers, departments and houses Runnable
class Teacher { constructor(name) { this.name = name; } }
class Student { constructor(name) { this.name = name; } }


// Association: a lesson USES a teacher and a student; it owns neither
class Lesson {
  constructor(teacher, student, topic) {
    this.teacher = teacher;
    this.student = student;
    this.topic = topic;
  }
  describe() { return `${this.teacher.name} teaches ${this.student.name}: ${this.topic}`; }
}


// Aggregation: a department HAS teachers, who exist on their own
class Department {
  teachers = [];
  constructor(name) { this.name = name; }
  add(teacher) { this.teachers.push(teacher); }
}


// Composition: a house OWNS its rooms; it creates them and they go with it
class Room { constructor(name) { this.name = name; } }
class House {
  #rooms;
  constructor(roomNames) { this.#rooms = roomNames.map(n => new Room(n)); }
  get roomCount() { return this.#rooms.length; }
}


const asha = new Teacher('Asha');
const ravi = new Student('Ravi');
console.log(new Lesson(asha, ravi, 'OOP').describe());


let science = new Department('Science');
science.add(asha);
console.log(science.teachers.length);
science = null;                      // department closed...
console.log(asha.name, 'still works here');


const home = new House(['Kitchen', 'Bedroom', 'Hall']);
console.log(home.roomCount);
Expected output
Asha teaches Ravi: OOP
1
Asha still works here
3
Opens this example in the full playground

Step-by-step explanation#

  1. Lesson receives an existing teacher and student and only uses them — association.
  2. Department collects teachers that were created outside it — aggregation.
  3. Setting science to null removes the department, but asha is still alive.
  4. House builds its own Room objects and keeps them private — composition. Nobody else holds a reference to those rooms.

Real-world use case#

In an e-commerce model, an Order is composed of OrderLines (delete the order, delete its lines), aggregates Products (products exist without the order) and is associated with a Customer.

Common mistakes#

Treating every has-a as composition

If parts are shared or outlive the container (a Product in many orders), it is aggregation. Deleting them with the container would be a bug.

Leaking composed parts

Returning the internal rooms array lets outside code keep or change parts the house should own. Return copies or read-only views.

Confusing relationships with inheritance

A House has Rooms; it is not a Room. Has-a is composition or aggregation, never inheritance.

Best practices#

  • Ask “who creates it and who deletes it?”
  • Keep composed parts private
  • Pass aggregated and associated objects in from outside
  • Model database cascade-delete on composition, not aggregation

Remember this#

Association = uses. Aggregation = has (parts survive). Composition = owns (parts die with it).

Container deleted → parts survive? Aggregation. Parts gone? Composition.

Has-a is never inheritance.

Practice exercise#

Your task: Create a Playlist that aggregates Song objects (songs exist independently) and a Song that is composed of a private Lyrics object it creates itself. Log the playlist length and the first line of a song’s lyrics.

Need a hint?
Playlist.add(song) stores an existing song; Song’s constructor creates new Lyrics(text).
Show solution
JavaScript Runnable
class Lyrics { constructor(text) { this.lines = text.split('|'); } }
class Song {
  #lyrics;
  constructor(title, text) { this.title = title; this.#lyrics = new Lyrics(text); }
  firstLine() { return this.#lyrics.lines[0]; }
}
class Playlist {
  songs = [];
  add(song) { this.songs.push(song); return this; }
}
const song = new Song('Morning', 'Wake up|Sun is up');
const list = new Playlist().add(song);
console.log(list.songs.length);  // 1
console.log(song.firstLine());   // Wake up
Opens this example in the full playground

Mini quiz#

Association, Aggregation and Composition quizMultiple choice Question 1 of 3

A Car has an Engine that is created with the car and scrapped with it. Which relationship is this?

Score so far: 0/0

Want more? Practise all OOP Concepts MCQs · OOP Concepts interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.