Programming with Objects

OOP Containment

Containment (aggregation) — the has-a relationship where one object holds other objects. Covers composition (created inside, cannot exist without the main object) vs aggregation (passed in, exists independently), with Car/Engine, Library/Books, School/Students, House/Rooms and Human/Heart examples, plus how containment differs from inheritance (is-a).

22.1 What is Containment?

Containment is an OOP concept where one class contains another class inside it. In simple terms, a big object is made from smaller objects.

A common phrase used to describe containment is:

The has-a relationship “A has-a B” — for example:
  • A car has an engine
  • A school has many students
  • A house has rooms

This “has-a” relationship helps you build programs that are organised, easy to understand, and close to real-life situations.

TermMeaning
Containment (aggregation)An OOP concept where one class contains another class inside it. A big object is made from smaller objects.
has-a relationshipThe phrase that describes containment: A has-a B (a car has an engine).
CompositionA strong form of containment where the contained object cannot exist without the main object (created inside).
AggregationA weaker form of containment where the contained object can exist on its own (passed in, not created inside).
Container classThe class that holds other objects (e.g. School, Library, Car).
Component classThe class that is held inside (e.g. Student, Book, Engine).
Key rule
  • Containment is a has-a relationship: one class contains another class inside it.
  • A big object is made from smaller objects.

22.2 Why Containment Matters — and vs Inheritance

Containment helps you in four ways:

  • Break a large problem into smaller parts — instead of making one giant class, you create smaller, focused classes and combine them.
  • Improve readability — each class handles one job, so your code becomes cleaner.
  • Reuse classes — once you create a class like Engine or Student, you can use it in other programs.
  • Model real-world objects — most real things are made up of smaller things. OOP tries to match this natural structure.

Students often confuse containment with inheritance. They are completely different concepts, and both are required in good program design:

Inheritance (is-a)Containment (has-a)
A relationship like "is-a"A relationship like "has-a"
Example: A Dog is an AnimalExample: A Dog has a Tail
The child class reuses the parent's attributes and methodsThe container class holds an object of another class as an attribute
Exam tip:
  • Examiners test whether you can tell has-a (containment) from is-a (inheritance).
  • “A Dog is an Animal” is inheritance; “A Dog has a Tail” is containment.
  • Mixing these up loses easy marks.

22.3 A Simple Example: Car and Engine

Let us start with an easy example that matches real life. A car cannot work without an engine. The car is the main object; the engine is a part inside it.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

class Car:
    def __init__(self):
        self.engine = Engine(150)   # Car contains an Engine

my_car = Car()
print(my_car.engine.horsepower)     # 150

The Car object contains an Engine object. When you create a Car, the Engine is automatically created inside it. This is containment — and because the Engine is created inside the Car, it is also composition.

Key rule
  • The container class creates an object of the component class inside its constructor: self.engine = Engine(150).
  • When you create the container, the component is automatically created inside it.
Your Turn — Your Turn — Phone and Battery [3 marks]
Write a class Battery with an attribute capacity, and a class Phone that contains a Battery (capacity 3000) created inside its constructor. Create a Phone and print the battery capacity.
Hint:
  • Battery: def __init__(self, capacity): self.capacity = capacity.
  • Phone: def __init__(self): self.battery = Battery(3000).
  • Main: p = Phone(); print(p.battery.capacity).

22.4 Containment with Multiple Objects

Containment can also mean “has many”. A library contains many book objects; a school contains many students. You store them in a list inside the container class.

class Book:
    def __init__(self, title):
        self.title = title

class Library:
    def __init__(self):
        self.books = []           # a list of Book objects

    def add_book(self, book):
        self.books.append(book)

# usage
b1 = Book("Hamlet")
b2 = Book("Macbeth")
lib = Library()
lib.add_book(b1)
lib.add_book(b2)
for b in lib.books:
    print(b.title)
Key rule
  • Containment with many objects uses a list: self.books = [].
  • The add_book method appends each object: self.books.append(book).
  • This models “has many”.
Task — Worked Example — School contains Students
Create a Student class (name, grade) and a School class that contains a list of students with an add_student method. Add two students and print their names.
Hint:
  • Step 1 — Student class with name and grade.
  • Step 2 — School class with self.students = [].
  • Step 3 — add_student(self, student): self.students.append(student).
  • Step 4 — create two Students, a School, add them, loop and print.
Your Turn — Your Turn — Course contains Modules [4 marks]
Write a Module class (name) and a Course class that contains a list of modules with an add_module method. Add three modules and print their names.
Hint:
  • Mirror the School/Student pattern: self.modules = [], add_module appends.
Composition note — Course and Module
  • In the Cambridge-style Course/Module example, a course is made of several modules.
  • If the Course object is destroyed, all modules inside it are also removed.
  • This is a strong form of containment known as composition.

22.5 Types of Containment: Composition vs Aggregation

There are two types of containment. The difference is whether the contained object can exist on its own.

TypeMain ideaCode patternExample
CompositionObject is created inside another object. The contained object cannot exist without the main object.self.part = Part()Car and Engine
AggregationObject is passed into another object. The contained object can exist on its own.self.parts.append(existing_part)School and Students
Composition — Car and Engine
  • The Car class creates the Engine itself.
  • The Engine cannot exist meaningfully without the Car.
  • The Car fully controls the Engine's lifetime.
# Composition
class Heart:
    def __init__(self):
        self.beats_per_minute = 72

class Human:
    def __init__(self):
        self.heart = Heart()   # Created inside the class

h = Human()
print(h.heart.beats_per_minute)   # 72
Task — Worked Example — House and Rooms (composition)
Write a Room class (room_type) and a House class that creates three Rooms inside its constructor (Bedroom, Kitchen, Living Room). Print each room type.
Hint:
  • House creates the Rooms inside __init__: self.rooms = [Room("Bedroom"), Room("Kitchen"), Room("Living Room")].
  • Loop over my_house.rooms and print room.room_type.
Your Turn — Your Turn — Car and Wheels (composition) [4 marks]
Write a Wheel class (position) and a Car class that creates four Wheels inside its constructor ("FL", "FR", "RL", "RR"). Print each wheel position.
Hint:
  • Mirror the House/Rooms pattern: Car creates the Wheels inside __init__.
Aggregation — School and Students
  • Student objects are created outside the School.
  • They can exist without being part of any School.
  • The School only “collects” them.
# Aggregation
class Student:
    def __init__(self, name):
        self.name = name

class School:
    def __init__(self):
        self.students = []        # Not created inside the class
    def add_student(self, student):
        self.students.append(student)

s1 = Student("Amina")   # created outside the School
s2 = Student("Hasib")   # created outside the School
my_school = School()
my_school.add_student(s1)
my_school.add_student(s2)
for s in my_school.students:
    print(s.name)
Task — Worked Example — School and Teachers (aggregation)
Write a Teacher class (name, subject) and a School class (name) with a list of teachers and add_teacher. Create two Teachers outside the School, add them, and print each teacher's name and subject.
Hint:
  • Teachers are created outside the School and passed in — this is aggregation.
  • School: self.teachers = [], add_teacher appends.
Your Turn — Your Turn — Library and Books (aggregation) [4 marks]
Write a Book class (title, author) and a Library class with a list of books and add_book. Create two Books outside the Library, add them, and print each title and author.
Hint:
  • Books are created outside the Library and passed in — aggregation.
Key rule — composition vs aggregation
  • Composition: the object is created inside (self.part = Part()) and cannot exist without the main object.
  • Aggregation: the object is passed in (self.parts.append(existing_part)) and can exist on its own.

22.6 How Containment Appears in Exams

In Cambridge exam questions, containment is usually tested in four forms:

  • Understanding relationships — identify whether a relation is “has-a” or “is-a”.
  • Drawing class diagrams — you may be given a scenario and asked to draw classes with links.
  • Writing classes — write classes that contain other classes.
  • Explaining the difference — explain the difference between composition, aggregation, and inheritance.
Full exam-style question — School with Teachers (aggregation) A school records its teachers. Each teacher has a name and a subject. The school has a name and a list of teachers.

(a) State whether the relationship between School and Teacher is “has-a” or “is-a”. [1]

(b) Write program code to declare a Teacher class with a constructor that takes a name and a subject. [3]

(c) Write program code to declare a School class with a constructor that takes a name and sets up an empty list of teachers, and an add_teacher method. [4]

(d) Explain whether this is composition or aggregation, giving a reason. [2]

Lab Task — Show full solution & mark scheme
Reveal the model solution and mark scheme for parts (a)–(d).
Hint:
  • (a) has-a (a school has teachers).
  • (b) class Teacher: __init__(self, name, subject) storing both as attributes.
  • (c) class School: __init__(self, name) with self.teachers = []; add_teacher(self, teacher) appends.
  • (d) aggregation — teachers are created outside the school and passed in, so they can exist on their own.

Key Points Summary

Containment is an OOP concept where one class contains another class inside it — a big object is made from smaller objects.
Containment is a "has-a" relationship: A car has an engine; a school has many students; a house has rooms.
Containment breaks large problems into smaller, focused classes, improves readability, enables reuse, and models real-world objects.
Inheritance is "is-a" (a Dog is an Animal); containment is "has-a" (a Dog has a Tail). They are completely different — do not confuse them.
In a simple containment example, the container class creates the component inside its constructor: self.engine = Engine(150). Creating the container automatically creates the component.
Containment with many objects uses a list: self.books = []. The add method appends: self.books.append(book). This models "has many".
Composition is a strong form of containment: the contained object is created inside (self.part = Part()) and cannot exist without the main object. Example: Car and Engine, House and Rooms, Human and Heart.
Aggregation is a weaker form of containment: the contained object is passed in (self.parts.append(existing_part)) and can exist on its own. Example: School and Students, Library and Books.
In composition, if the main object is destroyed, the contained object is also destroyed (the main object controls its lifetime).
In aggregation, the contained object is created outside and only collected by the container — it survives independently if the container is destroyed.
Code pattern — composition: self.part = Part() (created inside). Code pattern — aggregation: self.parts.append(existing_part) (passed in).
Containment appears in exams in four forms: identifying has-a vs is-a, drawing class diagrams, writing classes that contain other classes, and explaining composition vs aggregation vs inheritance.
A container class (e.g. School, Library, Car) holds component objects (e.g. Student, Book, Engine) as attributes.
When writing a container class, initialise the list in the constructor (self.students = []) and provide an add method (add_student) that appends to it.

22.7 Practice Tasks

Fifteen exam-style tasks. Click Hint for bullet-point guidance, then Help to reveal a worked Python solution.

1Practice Task — Has-a or is-a? [4 marks]
Classify each as has-a (containment) or is-a (inheritance): (i) A Car has an Engine, (ii) A Student is a Person, (iii) A Library has Books, (iv) A Dog is an Animal.
2Practice Task — Simple containment: Computer and CPU [3 marks]
Write a CPU class (speed) and a Computer class that contains a CPU (speed 3.5) created inside its constructor. Create a Computer and print the CPU speed.
3Practice Task — Containment with a list: Playlist and Songs [5 marks]
Write a Song class (title) and a Playlist class with a list of songs and add_song. Add three songs and print their titles.
4Practice Task — Composition: House and Rooms [4 marks]
Write a Room class (room_type) and a House class that creates three Rooms inside its constructor. Print each room type. Explain why this is composition.
5Practice Task — Aggregation: School and Students [5 marks]
Write a Student class (name) and a School class with a list of students and add_student. Create two Students outside the School, add them, print names. Explain why this is aggregation.
6Practice Task — Composition vs aggregation code patterns [2 marks]
State the code pattern that distinguishes composition from aggregation.
7Practice Task — Identify composition or aggregation [4 marks]
For each, state composition or aggregation: (i) Car and Engine, (ii) Library and Books, (iii) Human and Heart, (iv) School and Teachers.
8Practice Task — Write a container class: Team and Players [6 marks]
Write a Player class (name, position) and a Team class (team_name) with a list of players and add_player. Add two players and print each name and position.
9Practice Task — Composition with multiple objects: Car and Wheels [4 marks]
Write a Wheel class (position) and a Car class that creates four Wheels inside its constructor ("FL", "FR", "RL", "RR"). Print each position.
10Practice Task — Explain composition vs aggregation [4 marks]
Explain the difference between composition and aggregation, giving one example of each.
11Practice Task — Full containment: Invoice and LineItems [8 marks]
Write a LineItem class (description, price) and an Invoice class (customer) with a list of line items, add_item, and a total() method that returns the sum of prices. Add three items and print the total.
12Practice Task — Spot the relationship [2 marks]
A Book has a Cover. Is this containment or inheritance? Give a reason.
13Practice Task — Pseudocode containment [4 marks]
In Cambridge pseudocode, declare a class Engine with a Power attribute and a constructor NEW, and a class Car that contains an Engine (created inside NEW).
14Practice Task — Why use containment? [3 marks]
Give three reasons to use containment when designing a program.
15Practice Task — Exam-style: Team with Coach (aggregation) [9 marks]
Write a Coach class (name, speciality) and a Team class (team_name) with a list of coaches and add_coach. (a) State has-a or is-a [1]. (b) Write Coach [3]. (c) Write Team with add_coach [4]. (d) Composition or aggregation? Give a reason [2].

Question Bank

Answer all questions, then press Submit Quiz to see your score.

0/12 answered

Question 1Multiple Choice

Containment in OOP means:

Question 2Multiple Choice

Which is a has-a relationship?

Question 3True / False

Inheritance is an is-a relationship; containment is a has-a relationship.

Question 4Multiple Choice

In composition, the contained object is:

Question 5Multiple Choice

In aggregation, the contained object is:

Question 6Multiple Choice

Which is an example of composition?

Question 7Multiple Choice

Which is an example of aggregation?

Question 8True / False

In composition, if the main object is destroyed, the contained object is also destroyed.

Question 9Multiple Choice

How does a School class store multiple Student objects?

Question 10Multiple Choice

Why is containment useful?

Question 11Multiple Choice

In the Car/Engine example, when is the Engine created?

Question 12Multiple Choice

How does containment appear in Cambridge exams?

Answer all 12 questions to enable submission.