Skip to content

You are viewing a free preview of this lesson.

Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.

Object-Oriented Programming Principles

Object-Oriented Programming Principles

This lesson introduces the fundamental principles of Object-Oriented Programming (OOP) as required by the A-Level Computer Science specification. OOP is a programming paradigm that organises software design around objects rather than functions and logic. Understanding OOP is essential for writing maintainable, reusable, and scalable code.


What is Object-Oriented Programming?

Object-Oriented Programming is a paradigm in which programs are structured as collections of objects. Each object is an instance of a class and contains both data (attributes) and behaviour (methods). OOP models real-world entities and relationships, making complex software easier to design, understand, and maintain.

The four pillars of OOP are:

Pillar Description
Encapsulation Bundling data and methods together inside a class, hiding internal details from outside access.
Inheritance Creating new classes that reuse, extend, or modify the behaviour of existing classes.
Polymorphism Allowing objects of different classes to be treated as objects of a common superclass, with methods behaving differently depending on the object.
Abstraction Hiding complex implementation details and exposing only the essential features of an object.

Exam Tip: When asked to "explain OOP principles", you must name and define all four pillars. Simply listing them without explanation will not gain full marks.


Classes and Objects

A class is a blueprint or template that defines the attributes and methods that objects of that type will have. An object is a specific instance of a class, created at runtime with its own set of attribute values.

Pseudocode Example

CLASS Dog
    PRIVATE name: STRING
    PRIVATE breed: STRING
    PRIVATE age: INTEGER

    PUBLIC PROCEDURE new(n: STRING, b: STRING, a: INTEGER)
        name = n
        breed = b
        age = a
    END PROCEDURE

    PUBLIC FUNCTION getName() RETURNS STRING
        RETURN name
    END FUNCTION

    PUBLIC PROCEDURE bark()
        OUTPUT name + " says Woof!"
    END PROCEDURE
END CLASS

// Creating objects (instances)
myDog = NEW Dog("Rex", "Labrador", 5)
myDog.bark()  // Output: Rex says Woof!

Python Example

class Dog:
    def __init__(self, name: str, breed: str, age: int):
        self.__name = name      # Private attribute
        self.__breed = breed    # Private attribute
        self.__age = age        # Private attribute

    def get_name(self) -> str:
        return self.__name

    def bark(self):
        print(f"{self.__name} says Woof!")

# Creating objects
my_dog = Dog("Rex", "Labrador", 5)
my_dog.bark()  # Output: Rex says Woof!

Key Terminology

Term Definition
Class A template defining the attributes and methods for a type of object.
Object An instance of a class, holding specific attribute values.
Attribute A variable that belongs to an object, storing data about that object.
Method A function defined within a class that operates on the object's data.
Constructor A special method called when an object is created, used to initialise attributes.
Instantiation The process of creating an object from a class.

Encapsulation

Encapsulation is the principle of bundling data (attributes) and the methods that operate on that data into a single unit (a class), while restricting direct access to some of the object's components. This is achieved through access modifiers.

Access Modifiers

Modifier Description
Public Accessible from anywhere — inside or outside the class.
Private Accessible only from within the class itself.
Protected Accessible from within the class and its subclasses (used with inheritance).

Why Encapsulation Matters

  • Data protection: Private attributes cannot be accidentally modified by external code.
  • Controlled access: Getters and setters allow validation before data is read or changed.
  • Reduced coupling: Changes to the internal implementation do not affect code that uses the class.
  • Easier debugging: Bugs related to data can be traced to the class itself.

Getters and Setters

Getters and setters are methods that provide controlled access to private attributes.

class BankAccount:
    def __init__(self, owner: str, balance: float):
        self.__owner = owner
        self.__balance = balance

    def get_balance(self) -> float:
        return self.__balance

    def deposit(self, amount: float):
        if amount > 0:
            self.__balance += amount
        else:
            raise ValueError("Deposit amount must be positive")

    def withdraw(self, amount: float):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
        else:
            raise ValueError("Invalid withdrawal amount")

Exam Tip: In exam questions about encapsulation, always explain why attributes are made private — it is about preventing invalid data and protecting the object's internal state. Marks are awarded for explaining the benefit, not just stating the rule.


The this / self Reference

Inside a method, the keyword self (Python) or this (many other languages) refers to the current object — the specific instance on which the method was called. This allows methods to access the object's own attributes and other methods.

class Student:
    def __init__(self, name: str, grade: int):
        self.__name = name     # 'self' refers to the current object
        self.__grade = grade

    def promote(self):
        self.__grade += 1      # Modifies this specific student's grade

    def __str__(self):
        return f"{self.__name} (Year {self.__grade})"

Class Diagrams

A class diagram is a visual representation of a class, showing its name, attributes, and methods. It is part of UML (Unified Modelling Language) notation.

+----------------------------+
|          Dog               |
+----------------------------+
| - name: String             |
| - breed: String            |
| - age: Integer             |
+----------------------------+
| + new(n, b, a)             |
| + getName(): String        |
| + bark(): void             |
+----------------------------+

The symbols indicate access modifiers:

  • + means public
  • - means private
  • # means protected

Exam Tip: You may be asked to draw or interpret a class diagram in the exam. Make sure you understand the UML notation — particularly the difference between +, -, and # prefixes.


Static vs Instance Members

Feature Instance Members Static Members
Belongs to A specific object The class itself
Accessed via An object reference The class name
Shared? No — each object has its own copy Yes — shared across all instances
Use case Data unique to each object Data or behaviour common to all objects
class Student:
    student_count = 0  # Static (class) variable

    def __init__(self, name: str):
        self.__name = name
        Student.student_count += 1  # Shared counter

    @staticmethod
    def get_student_count() -> int:
        return Student.student_count

Summary

  • OOP organises programs around objects that combine data and behaviour.
  • A class is a blueprint; an object is an instance of a class.
  • Encapsulation hides internal data using access modifiers (public, private, protected).
  • Getters and setters provide controlled access to private attributes.
  • Class diagrams use UML notation to visualise classes and their members.
  • Static members belong to the class; instance members belong to individual objects.

Exam Tip: Many A-Level exam questions require you to write or trace through OOP code. Practise writing classes from scratch and predicting the output of given code fragments. Pay close attention to access modifiers — a common error is trying to access a private attribute from outside the class.