Mastering Object-Oriented Relationships: The Difference Between Association, Aggregation, and Composition

Kanan Joshi

--

Object-Oriented Programming (OOP) is built around how classes and objects relate to one another. In this blog, we take a closer look at four major OOP relationships: Association, Aggregation, and Composition. We’ll explain the theoretical concepts behind these relationships, highlight practical examples, and show you how to use them effectively in your own code. By the end of this article, you’ll have a solid understanding of these essential concepts and be able to apply them to design better systems.

Let us understand this with a mnemonic first:

Quick Mnemonic:

  • Association → “Uses” (Interaction: A Student uses a Teacher)
  • Aggregation → “Has-a” (Whole-Part: A Car has Wheels)
  • Composition → “Owns” (Ownership: A Library owns Books)

Association

Definition: Association represents a relationship between two classes where one class uses or interacts with the other but does not own it.

Scenario: A teacher can teach many students, and a student can taught by multiple teachers.

class Student:
def __init__(self, name, age):
self.name = name
self.age = age

def _get_student_data(self):
print(f"{self.name} is {self.age} years old.")

class Teacher:
def __init__(self, name, subject, students):
self.name = name
self.subject = subject
self.students = students

def _get_teacher_details(self):
print(f"{self.name} is teaching {self.subject}")

def _teaching_students(self):
students_list = [student.name for student in self.students]
print(f"{self.name} is teaching all {students_list}")

if __name__ == "__main__":

student1 = Student("Varsha", 12)
student2 = Student("Shivansh", 17)

student1._get_student_data()
student2._get_student_data()

teacher = Teacher("Radhika", "Maths", [student1, student2])
teacher._get_teacher_details()
teacher._teaching_students()

output:

Varsha is 12 years old.
Shivansh is 17 years old.
Radhika is teaching Maths
Radhika is teaching all [‘Varsha’, ‘Shivansh’]

Explanation of the Association:

  • Student and Teacher Relationship (Association):
  • A teacher has a list of Students: The Teacher class has a list of students, meaning each Teacher object knows about the Student objects it is associated with (i.e., the teacher teaches the students).
  • Student and Teacher Interaction: A Student object doesn't "own" the Teacher, nor does a Teacher object "own" the Student. Instead, they interact—teachers teach students, and students are taught by teachers. The relationship is one of interaction rather than ownership.

Aggregation

Definition: Aggregation is a special type of association where one class contains another as a part, but the part can exist independently of the whole.

Scenario: A Car has Wheels, but Wheels can exist separately from the Car.

class Wheel:
def __init__(self, company):
self.company = company

def get_wheel_details(self):
return f"This wheel is being manufactured by {self.company}."


class Car:
def __init__(self, model, wheels):
self.model = model
self.wheels = wheels

def get_car_details(self):
# Dictionary to store the count of wheels from each company
wheel_count = {}

# Counting how many wheels are from each company
for wheel in self.wheels:
wheel_count[wheel.company] = wheel_count.get(wheel.company, 0) + 1

# Printing details
print(f"{self.model} car has {len(self.wheels)} wheels:")
for company, count in wheel_count.items():
print(f" - {count} wheels from {company}")


if __name__ == "__main__":
# Create Wheel instances
wheel1 = Wheel("MRF")
wheel2 = Wheel("Goodyear")
wheel3 = Wheel("Bridgestone")

# Create Car instances
car1 = Car("Hyundai", [wheel1, wheel1, wheel1, wheel1]) # All MRF wheels
car2 = Car("TATA Harrier", [wheel1, wheel2, wheel2, wheel1]) # Mixed companies
car3 = Car("Ford Mustang", [wheel3, wheel3, wheel1, wheel1]) # Mixed companies

# Display car details
car1.get_car_details()
car2.get_car_details()
car3.get_car_details()

output:

Hyundai car has 4 wheels:
— 4 wheels from MRF
TATA Harrier car has 4 wheels:
— 2 wheels from MRF
— 2 wheels from Goodyear
Ford Mustang car has 4 wheels:
— 2 wheels from Bridgestone
— 2 wheels from MRF

Aggregation Explanation:

Aggregation Relationship: The Car class contains a list of Wheel objects. This signifies that a Car can have multiple Wheels, but the Wheels are independent and not owned by the Car. A wheel could be used in different cars, and if a car is destroyed, the wheels still exist and can be reused elsewhere.

Independence of Wheels: The Wheel objects are created independently and are then associated with a car. In the example, multiple wheels from different manufacturers (like MRF, Goodyear, and Bridgestone) are used, and these wheels can exist outside of the Car. If the car is removed from the system, the wheels still exist and can be assigned to another car.

No Ownership: Aggregation does not imply ownership, meaning that if a Car is deleted, the Wheel objects are not deleted. They can exist independently of the Car object. The wheels just “belong” to the car in terms of being associated with it, but they are not dependent on the car.

Composition

Definition: Composition is a stronger form of aggregation where one class owns another, and the lifetime of the owned class depends on the owner.

Scenario: A Library contains Books. If the library is closed, all books associated with it are also removed.

class Book:
def __init__(self, name, author):
self.name = name
self.author = author

def _get_book_details(self):
print(f"The author of the {self.book} book is {self.author}.")


class Library:
def __init__(self):
self.books = []

def _add_book(self, name, author):
book = Book(name, author)
self.books.append(book)

def _get_book_details(self):
books = [book.name for book in self.books]
print(f"This library contains {len(self.books)} number of books and the books are {books}")

def _remove_book(self, name):
for book in self.books:
if book.name == name:
self.books.remove(book)
print("After book removal available Books are : ")
self._get_book_details()


if __name__ == "__main__":
library = Library()

library._add_book("Rich Dad Poor Dad", "Robert T. Kiyosaki and Sharon Lechter")
library._add_book("Atomic Habbits", "James clear")
library._add_book("The Alchemist", "Paulo Coelho")

library._get_book_details()

library._remove_book("Atomic Habbits")

Output:

This library contains 3 number of books and the books are [‘Rich Dad Poor Dad’, ‘Atomic Habbits’, ‘The Alchemist’]
After book removal available Books are :
This library contains 2 number of books and the books are [‘Rich Dad Poor Dad’, ‘The Alchemist’]

Description:

  1. A Library contains a collection of Books.
  2. The Library owns the Books, meaning the books belong to that specific library.
  3. If the Library is deleted, the Books associated with it are also deleted.
  4. Books cannot exist without a Library in this composition model.

Summary:

In Object-Oriented Programming (OOP), understanding the relationships between classes is key. Here’s a quick breakdown:

  1. Association: Represents interaction between classes without ownership. Example: A Teacher teaches Students, but neither owns the other.
  2. Aggregation: A class contains another, but the contained class can exist independently. Example: A Car has Wheels, but the Wheels can exist without the Car.
  3. Composition: A stronger form of aggregation where one class owns another, and the owned class’s lifecycle depends on the owner. Example: A Library owns Books, and if the Library is deleted, so are the Books.

These concepts help design cleaner, more intuitive OOP systems.

--

--

No responses yet

Write a response