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.
On this page · 6 min · Intermediate
On this page
- In simple words
- Learning objectives
- Explanation
- Syntax
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 6 min
- Difficulty
- Intermediate
- Updated
- Oct 28, 2026
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#
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#
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);
Asha teaches Ravi: OOP 1 Asha still works here 3
Step-by-step explanation#
- Lesson receives an existing teacher and student and only uses them — association.
- Department collects teachers that were created outside it — aggregation.
- Setting science to null removes the department, but asha is still alive.
- 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#
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.
Returning the internal rooms array lets outside code keep or change parts the house should own. Return copies or read-only views.
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?
Show solution
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
Mini quiz#
A Car has an Engine that is created with the car and scrapped with it. Which relationship is this?
Want more? Practise all OOP Concepts MCQs · OOP Concepts interview questions
My notes#
Saved in this browser.