OOP With Multiple Classes (IB CS B3.2, HL): Inheritance, Polymorphism and More
IB CS B3.2 (HL) explained: inheritance, polymorphism, abstraction, composition vs aggregation, and design patterns, with diagrams, a worked example and exam tips.

In B3.1 you built a single class. Real programs are made of many classes that relate to one another, and B3.2 is about those relationships. This whole subtopic is HL only. It covers the ideas that make object-oriented code powerful and reusable: inheritance, polymorphism, abstraction, the difference between composition and aggregation, and a quick look at design patterns. The concepts connect, so let's take them one at a time.
What is inheritance? (HL)
Inheritance (HL) lets one class, the subclass (or child), take on the attributes and methods of another, the superclass (or parent). The subclass gets all that behaviour for free and can then add its own or change it.
This models an "is-a" relationship. A Dog is an Animal, so if Animal already defines name and eat(), the Dog class does not need to rewrite them; it inherits them and just adds bark(). The big win is code reuse: shared behaviour is written once in the superclass and used by every subclass.

What is polymorphism? (HL)
Polymorphism (HL) means "many forms". It is the idea that the same method call can behave differently depending on the type of object it is called on.
The most common form is overriding: a subclass provides its own version of a method it inherited. If Animal has a speak() method, Dog can override it to return "Woof", Cat to return "Meow", and Cow to return "Moo". You can then loop over a mixed list of animals, call speak() on each, and each one responds in its own way, without your loop needing to know which type it is holding. A related form is overloading: defining several methods with the same name but different parameters.

What is abstraction? (HL)
Abstraction (HL) is about hiding complexity behind a simple, common interface. An abstract class (or interface) defines what operations exist without saying how they work. It can declare a method with no body, and any subclass is then required to provide the actual implementation.
For example, an abstract Shape class can declare area() without defining it, because a generic shape has no single area formula. Then Circle implements area() as pi times radius squared, and Rectangle implements it as width times height. Code elsewhere can call area() on any shape without caring which kind it is. The abstract class says what must happen; each subclass decides how.

Composition vs aggregation (HL)
Inheritance is an "is-a" relationship. Often, though, one class simply contains another: a "has-a" relationship. B3.2 distinguishes two kinds, and the difference is about ownership and lifetime.
Composition (HL) is a strong "owns-a" relationship: the part cannot meaningfully exist without the whole. A Car has an Engine, and that engine is part of that specific car; if the car is destroyed, the engine goes with it. In a UML diagram, composition is shown with a filled diamond at the whole.
Aggregation (HL) is a weaker "has-a" relationship: the part can exist independently of the whole. A Team has Player objects, but a player still exists if the team disbands, and could even join another team. Aggregation is shown with a hollow diamond.

What are design patterns? (HL)
Design patterns (HL) are tried-and-tested, reusable solutions to problems that come up again and again when designing object-oriented systems. They are not code you copy in, but templates for how to structure classes.
You only need to recognise the idea and a few common examples. The singleton pattern ensures a class has only one instance, useful for something like a single settings manager. The factory pattern provides a method whose job is to create objects, hiding the exact class being made from the caller. The observer pattern lets objects subscribe to another object so they are notified automatically when it changes, like cells in a spreadsheet updating when a value they depend on changes. The point of patterns is that they give developers a shared vocabulary and proven structures, so you do not reinvent solutions every time.
Worked example: inheritance and a polymorphism trace (HL)
Inheritance and polymorphism are clearest with a trace. Start with a superclass and two subclasses that override one method.
Dog and Cat inherit the constructor and name from Animal (written once, reused), but each overrides speak(). Now loop over a mixed list and call the same method on each:
Trace which version of speak() runs for each object:
Object | Its class | speak() that runs | Output |
|---|---|---|---|
Dog("Rex") | Dog | Dog.speak() | Rex says Woof |
Cat("Bella") | Cat | Cat.speak() | Bella says Meow |
Animal("Thing") | Animal | Animal.speak() | Thing makes a sound |
That is polymorphism: one call, a.speak(), but the result depends on the object's actual class, and the loop never checks the type. Meanwhile name came from the superclass, so no subclass had to redefine it: that is inheritance giving you code reuse.
Your turn (guided practice). Add class Cow(Animal) that overrides speak() to return self.name + " says Moo". What does Cow("Daisy").speak() return, and did you need to rewrite the constructor? Answer: it returns "Daisy says Moo", and no, the constructor is inherited from Animal, so Cow reuses it.
A worked example: shapes done two ways
Suppose a drawing program needs many shapes that can each report their area. Inheritance and abstraction work together here.
Now use polymorphism to total the areas:
Trace the ideas. Shape is the abstraction (it defines area() but not how). Circle and Rectangle use inheritance to be shapes and override area(). The loop relies on polymorphism: it calls s.area() without knowing or caring which shape s actually is. That is the whole point of these tools working together.
Common exam mistakes
A frequent error is confusing "is-a" with "has-a". Inheritance is "is-a" (a Dog is an Animal). Composition and aggregation are "has-a" (a Car has an Engine). Choosing inheritance when a containment relationship is meant is a classic slip.
Students also mix up composition and aggregation. The test is the part's lifetime: if the part dies with the whole, it is composition (filled diamond); if it survives independently, it is aggregation (hollow diamond).
With polymorphism, remember that overriding (same method, redefined in a subclass) is different from overloading (same name, different parameters). Questions often ask you to name or distinguish the forms.
Finally, do not overstate design patterns. You are expected to explain the idea and recognise common ones, not implement complex frameworks. Keep your examples simple and correct.
Quick recap
This whole subtopic is HL only. Inheritance gives a subclass the superclass's members ("is-a"), enabling code reuse. Polymorphism lets the same call behave differently per type, mainly through method overriding. Abstraction hides how something works behind a simple interface that subclasses implement. Composition is a strong "owns-a" (part dies with the whole); aggregation is a weak "has-a" (part lives on); design patterns are reusable design templates.
Frequently asked questions
What is inheritance in OOP? Inheritance lets a subclass take on the attributes and methods of a superclass, modelling an "is-a" relationship such as a Dog being an Animal. The subclass reuses the superclass's code and can add its own members or override inherited ones. This is HL content.
What is polymorphism? Polymorphism means the same method call can behave differently depending on the object's type. The main form is overriding, where a subclass redefines an inherited method, so a single call like speak() produces different results for a Dog, Cat or Cow. This is HL content.
What is the difference between overriding and overloading? Overriding is when a subclass replaces an inherited method with its own version of the same signature. Overloading is when several methods share a name but take different parameters. Both are forms of polymorphism, but they solve different problems. This is HL content.
What is abstraction in OOP? Abstraction hides complexity behind a simple interface. An abstract class declares what operations exist, often without implementing them, and each subclass provides the actual behaviour. Calling code can use the interface without knowing the details. This is HL content.
What is the difference between composition and aggregation? Both are "has-a" relationships. Composition is a strong relationship where the part cannot exist without the whole, like an Engine in a Car. Aggregation is weaker, where the part can exist independently, like a Player in a Team. This is HL content.
What are design patterns? Design patterns are reusable, proven solutions to common object-oriented design problems, such as the singleton, factory and observer patterns. They are templates for structuring classes rather than ready-made code, and they give developers a shared vocabulary. This is HL content.
Looking for a printable summary? Grab the OOP Inheritance, Polymorphism and More, a four-page knowledge organiser covering everything above.
Looking for an IB Computer Science tutor?
Hi, I'm Yuness, the tutor behind Shuttle Learning. I work one to one with IB Computer Science students at SL and HL, and I deliberately take on only a handful each year so every student gets my full attention. Most go on to earn the 6s and 7s they were aiming for, in the final exams and the IA alike.
If you would like that kind of support, book a free 15-minute call and tell me what you are stuck on. You can press BOOK A LESSON .