How does object-oriented programming model real things as classes and objects, and what do encapsulation and inheritance give us?
Define classes with attributes and methods, create objects, and apply encapsulation, inheritance and polymorphism in Python
A focused answer to the H2 Computing outcome on object-oriented programming. Classes and objects, attributes and methods, the constructor, and the principles of encapsulation, inheritance and polymorphism in Python.
Reviewed by: AI editorial process; not yet individually human-reviewed
Have a quick question? Jump to the Q&A page
Jump to a section
What this dot point is asking
SEAB wants you to define classes with attributes and methods, create objects from them, and apply the three core principles - encapsulation, inheritance and polymorphism - in Python. The central idea is that object-oriented programming bundles data and the operations on that data together into objects, so a program is modelled as interacting things rather than loose variables and functions.
The answer
Classes and objects
A class is a blueprint describing a kind of thing; an object is a specific instance of it. A class defines attributes (data) and methods (functions that act on that data):
class Dog:
def __init__(self, name, age): # constructor
self.name = name # attributes
self.age = age
def bark(self): # method
return f"{self.name} says woof"
rex = Dog("Rex", 3) # an object (instance)
print(rex.bark())
The constructor __init__ runs when an object is created, initialising its attributes. self refers to the particular object the method is acting on.
Encapsulation
Encapsulation bundles data with the methods that use it and hides the internal data behind those methods. In Python a leading double underscore marks an attribute as private:
self.__balance = 0 # private; access only through methods
External code cannot change __balance directly; it must call methods that enforce the rules (a deposit must be positive, a withdrawal cannot overdraw). This keeps the object's data valid.
Inheritance
Inheritance lets a subclass acquire a parent class's attributes and methods, then add or override behaviour:
class Animal:
def speak(self):
return "..."
class Cat(Animal): # Cat inherits from Animal
def speak(self): # override
return "meow"
This reuses shared code in the parent and lets each subclass specialise. A new kind of animal is just a new subclass.
Polymorphism
Polymorphism lets objects of different classes be used through a common interface, each responding to the same call in its own way:
for animal in [Cat(), Dog("Rex", 3), Animal()]:
print(animal.speak()) # the right version runs for each
The calling code does not need to know each object's exact type; it just calls speak() and the correct overridden method runs.
Examples in context
Example 1. A game with many entities. A game defines a Sprite parent with shared position and a draw() method, and subclasses Player, Enemy and Coin that override draw() and update(). The main loop iterates all sprites calling update() polymorphically, so adding a new entity type means adding one subclass, not editing the loop.
Example 2. A payroll system. An Employee class encapsulates pay details behind a calculate_pay() method; SalariedEmployee and HourlyEmployee subclasses override it with their own rules. Encapsulation guarantees pay is computed only through validated methods, and polymorphism lets the system total a mixed list of employees uniformly.
Try this
Q1. Distinguish between a class and an object. [2 marks]
- Cue. A class is the blueprint defining attributes and methods; an object is a specific instance created from that class.
Q2. How does encapsulation protect an object's data? [2 marks]
- Cue. It makes data private and accessible only through methods that enforce rules, so external code cannot set invalid values directly.
Q3. What does it mean to override a method in a subclass? [1 mark]
- Cue. The subclass redefines an inherited method with its own version, which runs in place of the parent's for objects of that subclass.
Exam-style practice questions
Practice questions written in the style of SEAB exam questions on this dot point, with worked answer explainers. The year tag is the paper they imitate, not the source.
Original6 marksWrite a Python class `BankAccount` with a private balance, a constructor taking an opening balance, a `deposit(amount)` method and a `withdraw(amount)` method that refuses to overdraw. Explain how this demonstrates encapsulation.Show worked answer →
class BankAccount:
def __init__(self, opening):
self.__balance = opening # private attribute
def deposit(self, amount):
if amount > 0:
self.__balance = self.__balance + amount
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance = self.__balance - amount
return True
return False # refuse to overdraw
def get_balance(self):
return self.__balance
This demonstrates encapsulation: the balance is a private attribute (__balance), so outside code cannot change it directly. All access goes through methods that enforce rules - deposits must be positive, withdrawals cannot exceed the balance. The object protects its own data and guarantees it stays valid.
Markers reward a constructor setting a private attribute, deposit and guarded withdraw methods, and the explanation that encapsulation hides data behind methods that enforce validity.
Original5 marks(a) Define inheritance and polymorphism. (b) A `Shape` class has a method `area()`. Explain how a `Circle` subclass and a `Rectangle` subclass use inheritance and polymorphism. (c) State one benefit of inheritance.Show worked answer →
(a) Inheritance lets a subclass acquire the attributes and methods of a parent class, optionally adding or overriding behaviour. Polymorphism lets objects of different classes be treated through a common interface, with each responding to the same method call in its own way.
(b) Circle and Rectangle inherit from Shape, so they are both shapes. Each overrides area() with its own formula. Polymorphism means a list of mixed Shape objects can be looped over calling area() on each, and the correct version runs for each object's actual type, without the calling code knowing which shape it is.
(c) A benefit of inheritance is code reuse - shared behaviour is written once in the parent and inherited by all subclasses - and easier extension, since a new shape just adds a subclass.
Markers reward correct definitions, the subclasses overriding area() and being used through the common Shape interface, and a benefit such as code reuse.
Related dot points
- Use Python selection, iteration and functions with parameters and return values to structure a solution, applying scope correctly
A focused answer to the H2 Computing outcome on Python control flow. Selection with if and elif, iteration with for and while, defining functions with parameters and return values, and local versus global scope.
- Handle runtime errors with try and except, and read from and write to text files safely in Python
A focused answer to the H2 Computing outcome on exceptions and files. The try, except, else and finally blocks, raising exceptions, and reading and writing text files safely with the with statement.
- Apply decomposition, modularity and abstraction to structure software, explaining the benefits for maintenance and reuse
A focused answer to the H2 Computing outcome on decomposition and abstraction. Breaking problems into modules, the role of interfaces, information hiding through abstraction, and the benefits for maintainability and reuse.
- Design test cases using normal, boundary and erroneous data, distinguish levels of testing, and apply systematic debugging techniques
A focused answer to the H2 Computing outcome on testing and debugging. Choosing normal, boundary and erroneous test data, unit and integration and system testing, black-box versus white-box, and systematic debugging.
- Describe arrays and records as data structures, explain constant-time array indexing and contrast static with dynamic arrays
A focused answer to the H2 Computing outcome on arrays and records. Contiguous storage and constant-time indexing, one and two dimensional arrays, records as fields of mixed type, and static versus dynamic arrays.