First exams 2027 · HL only

B3.2.4 · Fundamentals of OOP for multiple classes (HL)

Composition and aggregation

Building a big object out of smaller ones, and deciding whether those smaller ones belong to it or merely work with it.

HL only Typically 3–6 marks · AO1/AO2 Command term: explain

Explainer

Alderway Community Radio schedules a programme called Evening Review. The programme is built from segments: a five-minute headline read, a twenty-minute studio interview, each written specifically for that episode. It also has presenters: two members of station staff who are rostered onto it. Both are things the programme "has". But if Evening Review is cancelled tomorrow, its segments are meaningless and should go with it, while its presenters turn up on Monday and host something else.

Df

Inheritance builds a class by saying what it is. Composition and aggregation build one by saying what it has: an object holds references to other objects, and delegates work to them, instead of trying to do everything itself.

This is what the syllabus means by designing objects from smaller component objects. Programme does not calculate a running time by knowing about minutes; it asks each Segment it holds. The two relationships differ only in who owns the lifetime of the parts.

You have met these three relationship names before, on B3.1.2, as UML notation. This statement is about what they mean once you are writing the classes themselves.

Explainer

The two kinds of has-a

Df

Composition is a whole-part relationship where the part cannot exist outside its whole. The whole creates its parts, owns them for as long as it lives, and takes them with it when it goes. The two are tightly coupled.

Df

Aggregation is a whole-part relationship where the part exists independently. It was created elsewhere, is merely referenced by the whole, can be shared with other wholes at the same time, and carries on existing after the whole is destroyed.

The deciding question

Ask what should happen to the part when the whole is deleted. If the answer is "it should be deleted too, it means nothing on its own," that is composition. If the answer is "it should carry on, something else may still be using it," that is aggregation.

Two that are composition

A post and its comments

Post
Comment

A comment is written onto one particular post and is stored with it. Delete the post and every comment goes with it, because a reply to something that no longer exists means nothing. No other post could ever adopt them.

A quiz attempt and its answers

QuizAttempt
Answer

Each answer belongs to one sitting of the quiz. Wipe the attempt and the answers are meaningless: "C" on its own is not information once you no longer know which attempt or question it belonged to.

Two that are aggregation

A squad and its players

Squad
Player

A player existed before joining and carries on after transferring out. The same player object can sit in a club squad and a national squad at the same time, which composition could never allow.

A basket and the products in it

Basket
Product

A product exists in the shop's catalogue whether or not anyone has added it to a basket, and the same product sits in hundreds of baskets at once. Emptying one basket must not delete the product.

filled diamond = composition hollow diamond = aggregation the diamond always sits at the whole end

Worked example

The difference is visible in the constructor

This is the most useful thing to recognise on a code-reading question, because the two look almost identical everywhere else.

class Programme:
    def __init__(self, name, presenters):
        self.name = name

        # AGGREGATION: they already existed, they arrive as a parameter
        self.presenters = presenters

        # COMPOSITION: built right here, by and for this programme
        self.segments = [
            Segment("Headlines", 5),
            Segment("Studio interview", 20)
        ]

    def running_time(self):          # delegates to its parts
        total = 0
        for s in self.segments:
            total += s.minutes
        return total
public class Programme {
    private String name;
    private List<Presenter> presenters;
    private List<Segment> segments;

    public Programme(String name, List<Presenter> presenters) {
        this.name = name;

        // AGGREGATION: handed in from outside, not created here
        this.presenters = presenters;

        // COMPOSITION: this object builds its own parts
        this.segments = new ArrayList<>();
        this.segments.add(new Segment("Headlines", 5));
        this.segments.add(new Segment("Studio interview", 20));
    }
}

The tell: where the part object is created. Composed parts are constructed inside the whole, so nothing else can ever hold a reference to them. Aggregated parts are constructed outside and passed in, which is precisely how they survive the whole and how two wholes can share the same one.

Worked example

Delete the programme and see what survives

Alderway cancels Evening Review. Press the button and watch which objects go with it. Morning Show is a second programme that happens to share a presenter.

Wholes
ProgrammeEvening Review
ProgrammeMorning Show
Composed parts · owned by one programme
SegmentHeadlines (5 min)
SegmentStudio interview (20 min)
SegmentMorning bulletin (4 min)
Aggregated parts · station staff
PresenterNadia
PresenterTom

Evening Review holds two segments of its own, and is rostered to Nadia and Tom. Nadia also presents Morning Show.

Tom is the interesting one. He presents nothing else, yet he still survives, because aggregation is about independent existence, not about being shared. Sharing is something aggregation makes possible, not something it requires.

Explainer

Choosing between them when you design

Composition

Real example: Programme and its Segment objects, built in the constructor and owned outright.

Advantage

  • The whole controls its parts completely (nothing outside can hold a reference and change a segment behind the programme's back, so the programme can always trust its own running time)

Disadvantage

  • Tightly coupled, and not reusable (a segment cannot be lifted out and given to another programme, and the two classes now have to change together)
Aggregation

Real example: Programme and its Presenter objects, employed by the station and passed in.

Advantage

  • One object can serve many wholes (a presenter exists once in the system and appears on every programme they host, so updating their contact details updates it everywhere)

Disadvantage

  • The whole cannot rely on exclusive control (another part of the program holds the same object and may change it at any time, and deleting the whole leaves the part behind, which has to be tidied up separately)

Both are usually preferable to inheritance when the relationship is genuinely "has-a" rather than "is-a". A programme is not a kind of segment, and a segment is not a kind of programme, so no inheritance hierarchy would model this well however it were arranged.

Try it yourself

Prove the parts are shared, or not

Two programmes, one shared presenter. The counter at the end is the proof: because both programmes hold the same Presenter object, incrementing it from either one is visible from the other. Try doing the same with a segment and watch it fail.

main.py
Loading Python engine…
Output
Press Run to see the output here.

Running in offline fallback mode. The full Python engine couldn’t load (blocked school network, or no internet), so this console switched automatically to a small hand-written engine. It runs this page’s scenario, including shared object references, but it isn’t full Python.

Check your understanding

A Playlist class receives Track objects as a constructor parameter, and the same Track appears on three different playlists. Deleting one playlist must not affect the others. Which relationship is this, and why?

Common mistake

Markers reported this pattern for B3.2.4

RecurringCandidates justify their choice using how many parts there are rather than how long the parts live. "A programme has several segments, so it is composition" is not an argument, because aggregation involves several parts just as often. Quantity never distinguishes the two.

The second error is treating "the whole has a reference to the part" as evidence of composition. Both relationships hold references; that is what makes them both has-a relationships in the first place. What separates them is whether the part was created inside the whole and dies with it.

Answer frame that scores: state where the part is created → state what happens to it when the whole is destroyed → name the relationship that follows from those two facts.

✕

What a weak answer looks like: “Programme and Presenter is composition because a programme is made up of its presenters.” It describes a has-a relationship correctly and then picks the wrong one, with no reference to lifetime at all.

✓

What it should say: “Programme and Presenter is aggregation: presenters are created by the station and passed into the constructor, so the same presenter can appear on several programmes and still exists once a programme is cancelled. Programme and Segment is composition, because the segments are constructed inside Programme and are meaningless without it.” Creation point, lifetime, and the name that follows.

Revision questions

Past-paper style. Write an answer, then reveal the marking points and mark yourself.

Question 1 · 3 marks

[3]Explain why Programme and Segment is composition, while Programme and Presenter is aggregation.

Question 2 · 4 marks

[4]Alderway adds a StudioBooking class. A booking exists only for one programme and is discarded when that programme is cancelled. Construct the class relationship in code, and justify your choice.

Question 3 · 4 marks

[4]A developer suggests making Programme inherit from Segment so it can reuse the minutes attribute. Evaluate this suggestion.

Flashcards

Active recall for this statement’s key terms.