All subjects · Computer Science · WCP04 Advanced Practical Programming and Problem-solving
Inheritance, polymorphism, aggregation, composition and UML
Edexcel IAL Computer Science · WCP04 Advanced Practical Programming and Problem-solving
Classes can be built from other classes. Inheritance shares code between related classes, polymorphism lets one call behave correctly for many types, and aggregation and composition build objects out of other objects. UML class diagrams describe all of this, and you must turn them into code.
Inheritance
A subclass (child) inherits the attributes and methods of its superclass (parent) and can add its own: class Employee(Person):.
super().__init__(name)runs the parent's constructor, so the inherited attributes are set without repeating code.- A subclass can override a method by defining one with the same name.
isinstance(obj, Person)is True for a Person or any subclass of Person.
Polymorphism, aggregation and composition
- Polymorphism: objects of different classes respond to the same method call in their own way. A loop calling
p.describe()works for Person and Employee objects alike, and each runs its own version. - Aggregation ('has a', weak): an object holds references to objects that exist independently. A Department holds Employees; if the department is closed, the employees still exist.
- Composition ('owns a', strong): an object creates its parts, and they exist only as part of it. A Car creates its Engine inside its constructor.
class Person:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name}"
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # reuse the parent's constructor
self._salary = salary
def describe(self): # overrides Person.describe
return f"{self.name}, salary {self._salary}"
class Department:
def __init__(self, title):
self.title = title
self.staff = [] # aggregation: holds existing Employee objects
def add(self, employee):
self.staff.append(employee)
def payroll(self):
return sum(e._salary for e in self.staff)
people = [Person("Ira"), Employee("Jo", 30000), Employee("Ky", 32000)]
for p in people:
print(p.describe()) # polymorphism: the right method for each object
sales = Department("Sales")
sales.add(people[1])
sales.add(people[2])
print(sales.title, sales.payroll(), isinstance(people[1], Person))Output:
Ira
Jo, salary 30000
Ky, salary 32000
Sales 62000 TrueMore polymorphism and composition
class Engine:
def __init__(self, power):
self.power = power
class Car:
def __init__(self, model, power):
self.model = model
self.engine = Engine(power) # composition: the car creates and owns its engine
class Shape:
def area(self):
return 0
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return round(3.14159 * self.r * self.r, 2)
print(Car("Hatch", 90).engine.power, [s.area() for s in [Square(3), Circle(1), Shape()]])Output:
90 [9, 3.14, 0]UML class diagrams
A class is drawn as a box with three sections: the class name, the attributes, and the methods.
- Visibility: + public, - private, # protected. Types may follow a colon:
- balance: float,+ deposit(amount: float). - Inheritance: a line with a hollow triangle pointing at the parent class.
- Aggregation: a line with a hollow diamond at the 'whole' end (Department).
- Composition: a line with a filled diamond at the 'whole' end (Car).
- Multiplicities such as 1 and 0..* show how many objects are linked.
| UML | Python |
|---|---|
| Class Employee, inheriting from Person | `class Employee(Person):` |
| - salary: int | `self.__salary` set in `__init__` |
| # grade: str | `self._grade` |
| + describe(): str | `def describe(self):` returning a str |
| Department, hollow diamond, 0..* Employee | `self.staff = []` filled by an `add(employee)` method |
| Car, filled diamond, 1 Engine | `self.engine = Engine(...)` inside `Car.__init__` |
Worked example
A UML diagram shows class Student inheriting from Person, with '- grade: int' and '+ describe(): str' that adds the grade to Person's description. Write Student.
- ```python class Person: def __init__(self, name): self.name = name def describe(self): return f"{self.name}" class Employee(Person): def __init__(self, name, salary): super().__init__(name) # reuse the parent's constructor self._salary = salary def describe(self): # overrides Person.describe return f"{self.name}, salary {self._salary}" class Student(Person): def __init__(self, name, grade): super().__init__(name) self.__grade = grade def describe(self): return super().describe() + f", grade {self.__grade}" print(Student("Lin", 12).describe()) ```
- Output: ``` Lin, grade 12 ```
Answer: super() is used twice: to set the inherited name, and to reuse the parent's describe() before adding to it. The minus sign in UML becomes a double-underscore private attribute.
Check yourself
- The Shape, Square and Circle classes from the lesson are included in the code below. What does this print?
```python
class Engine:
def __init__(self, power):
self.power = power
class Car:
def __init__(self, model, power):
self.model = model
self.engine = Engine(power) # composition: the car creates and owns its engine
class Shape:
def area(self):
return 0
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
class Circle(Shape):
def __init__(self, r):
self.r = r
def area(self):
return round(3.14159 * self.r * self.r, 2)
shapes = [Square(2), Circle(2), Square(1)]
print(sum(s.area() for s in shapes))
```
Show answer
17.57. Each object uses its own area method: 4 + 12.57 + 1 = `17.57`
- The Person, Employee and Department classes from the lesson are included in the code below. What does this print?
```python
class Person:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name}"
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # reuse the parent's constructor
self._salary = salary
def describe(self): # overrides Person.describe
return f"{self.name}, salary {self._salary}"
class Department:
def __init__(self, title):
self.title = title
self.staff = [] # aggregation: holds existing Employee objects
def add(self, employee):
self.staff.append(employee)
def payroll(self):
return sum(e._salary for e in self.staff)
e = Employee("Ama", 25000)
print(e.describe(), Person.describe(e))
```
Show answer
Ama, salary 25000 Ama. e.describe() runs the overriding Employee method; calling Person.describe(e) directly runs the parent's version. Output: `Ama, salary 25000 Ama`
- The Person, Employee and Department classes from the lesson are included in the code below. What does this print?
```python
class Person:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name}"
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # reuse the parent's constructor
self._salary = salary
def describe(self): # overrides Person.describe
return f"{self.name}, salary {self._salary}"
class Department:
def __init__(self, title):
self.title = title
self.staff = [] # aggregation: holds existing Employee objects
def add(self, employee):
self.staff.append(employee)
def payroll(self):
return sum(e._salary for e in self.staff)
d = Department("IT")
e = Employee("Bo", 40000)
d.add(e)
d.add(Employee("Cy", 35000))
del d
print(e.name, e._salary)
```
Show answer
Bo 40000. Aggregation: the department only held references. Deleting d leaves the employee object e untouched. Output: `Bo 40000`
- The Person, Employee and Department classes from the lesson are included in the code below. What does this print?
```python
class Person:
def __init__(self, name):
self.name = name
def describe(self):
return f"{self.name}"
class Employee(Person):
def __init__(self, name, salary):
super().__init__(name) # reuse the parent's constructor
self._salary = salary
def describe(self): # overrides Person.describe
return f"{self.name}, salary {self._salary}"
class Department:
def __init__(self, title):
self.title = title
self.staff = [] # aggregation: holds existing Employee objects
def add(self, employee):
self.staff.append(employee)
def payroll(self):
return sum(e._salary for e in self.staff)
p = Person("Di")
e = Employee("Ed", 1)
print(isinstance(e, Person), isinstance(p, Employee))
```
Show answer
True False. Every Employee is a Person, but a Person is not necessarily an Employee. Output: `True False`
- What does `super().__init__(name)` do in Employee's constructor?
- Creates a new Person object separate from the Employee
- Runs Person's constructor so the inherited name attribute is set
- Makes name a private attribute
- Calls Employee's constructor again
Show answer
Runs Person's constructor so the inherited name attribute is set. It reuses the parent's initialisation code on the same object.
- A School object creates its own Timetable object in its constructor, and the timetable has no use without that school. Which relationship is this?
- Aggregation
- Inheritance
- Polymorphism
- Composition
Show answer
Composition. The part is created and owned by the whole and does not exist independently: composition (filled diamond in UML).
- In a UML class diagram, what does '- score: int' in the attribute section mean?
- A public attribute called score
- A private attribute called score of type int
- A method that subtracts from score
- A protected attribute called score
Show answer
A private attribute called score of type int. The minus sign means private; in Python, write self.__score.
- How is inheritance shown between two classes on a UML class diagram?
- A line with a hollow triangle pointing at the parent class
- A line with a filled diamond at the parent class
- A dotted line with no arrowhead
- A line with a hollow diamond at the child class
Show answer
A line with a hollow triangle pointing at the parent class. The hollow triangle arrowhead points from the subclass to the superclass.
Sources
- Pearson Edexcel International Advanced Subsidiary/Advanced Level in Computer Science specification, Issue 1 (March 2026)
- Pearson Edexcel IAL Computer Science Unit 4 Programming Language Subset (PLS)
- Pearson Edexcel IAL Computer Science sample assessment materials (Unit 3 and Unit 4)
Last updated 8 November 2026. Spotted a mistake? Tell us.