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.
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.
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
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.
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.
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
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
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
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
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.
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
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)
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.
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
B3.2.4RecurringCandidates 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.
[3]Explain why Programme and Segment is composition, while Programme and Presenter is aggregation.
Marking points
评分要点
- Programme and Segment is composition: a segment belongs to exactly one programme, is created as part of it, and is destroyed when the programme is deleted.
- Programme and Presenter is aggregation: a presenter exists independently, can work on several programmes, and continues to exist if a programme is cancelled.
- The difference is lifetime and ownership: the segment shares the programme's lifetime, the presenter does not.
- Programme 和 Segment 是组合:一个片段恰好属于一档节目,作为其一部分被创建,并在节目被删除时被销毁。
- Programme 和 Presenter 是聚合:一位主持人独立存在,可以参与多档节目,并在某档节目被取消时继续存在。
- 区别在于生命周期和所有权:片段共享节目的生命周期,主持人则不然。
[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.
Marking points
评分要点
- A StudioBooking exists only for one programme and is discarded with it, so this is composition.
- In code: the Programme constructor creates its StudioBooking (self.booking = StudioBooking(...)), and nothing outside holds a reference to it.
- When the Programme object is deleted, its StudioBooking is no longer referenced and goes with it.
- Justification: the booking has no independent existence or meaning without its programme, which is exactly the composition relationship.
- 一次 StudioBooking 只为一档节目存在,并随它一同被丢弃,所以这是组合。
- 在代码中:Programme 构造函数创建它的 StudioBooking(self.booking = StudioBooking(...)),外部没有东西持有对它的引用。
- 当 Programme 对象被删除时,它的 StudioBooking 不再被引用,随之消失。
- 理由:这次预订离开它的节目就没有独立的存在或意义,这正是组合关系。
[4]A developer suggests making Programme inherit from Segment so it can reuse the minutes attribute. Evaluate this suggestion.
Marking points
评分要点
- Inheritance models an is-a relationship, but a programme is not a kind of segment, so Programme inheriting from Segment is a false hierarchy.
- It would give Programme a single minutes attribute, when a programme actually has many segments each with their own minutes.
- It also drags in every other Segment method, which makes no sense for a Programme.
- The right approach is composition: Programme holds a list of Segment objects and computes its running time by summing their minutes.
- Evaluation: reject the suggestion; use composition, not inheritance, to reuse the attribute.
- 继承建模 is-a 关系,但一档节目不是一种片段,所以 Programme 继承 Segment 是一个错误的层级。
- 它会给 Programme 一个单一的 minutes 属性,而一档节目实际上有许多片段,每个都有自己的 minutes。
- 它还会拖入 Segment 的其他所有方法,对 Programme 毫无意义。
- 正确的做法是组合:Programme 持有一个 Segment 对象的列表,并通过把它们的 minutes 相加来计算自己的运行时间。
- 评价:拒绝该建议;用组合而不是继承来复用这个属性。
Flashcards
Active recall for this statement’s key terms.
Keep this statement’s practice with you
Free account: unlock every revision question and flashcard for B3.2.4, and every other IB CS 2027 statement.