Introduction to Object-Oriented Programming

advanced25 min

Learning objectives

  • Explain why OOP exists
  • Distinguish between classes and objects

Learn

AQA 4.1.2.3 — Object-oriented programming

Retrieval: the previous lesson evaluated procedural programming's genuine limitation: as a system grows, data (a dictionary) and the functions that operate on it drift apart, coupled only loosely, with nothing protecting the data's structure. Object-Oriented Programming exists specifically to address that.

Key vocabulary

  • Class — a blueprint that defines what attributes and methods its objects will have.
  • Object — a specific instance created from a class; a real, individual "thing" built from the blueprint.
  • Attribute — a piece of data belonging to an object.
  • Method — a function belonging to an object, defined inside its class.
  • Constructor (__init__) — the special method that runs automatically when a new object is created, setting up its initial state.

Understand — bundling data and behaviour together

Where procedural code kept a student's data in a separate dictionary and passed it into standalone functions, OOP bundles both into one unit: a Student object is the data (its attributes) and knows how to act on itself (its methods) — the two are no longer separate things connected only by parameters. This directly closes the coupling gap the previous lesson identified: a method defined inside the class is the one place responsible for that class's own data.

See it — the Student class

class Student:
    def __init__(self, name, year_group):   # constructor
        self.name = name                     # attribute
        self.year_group = year_group         # attribute

    def introduce(self):                     # method
        print(f"Hi, I'm {self.name} in Year {self.year_group}.")

aisha = Student("Aisha", 13)   # instantiation
tom = Student("Tom", 12)

aisha.introduce()   # "Hi, I'm Aisha in Year 13."
tom.introduce()      # "Hi, I'm Tom in Year 12."

__init__ runs automatically when a new object is created. self refers to the specific object a method is being called on — it's how aisha.introduce() knows to use Aisha's name and year group, not Tom's, even though both objects were built from the exact same class.

See it — a second class, same pattern: Book

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_available = True

    def describe(self):
        status = "available" if self.is_available else "on loan"
        return f"{self.title} by {self.author} ({status})"

hobbit = Book("The Hobbit", "J.R.R. Tolkien")
print(hobbit.describe())   # "The Hobbit by J.R.R. Tolkien (available)"

This Book class is the foundation this whole sequence's practical work will keep building on, lesson by lesson.

Identify it — class, object, attribute or method?

For the Book class above, identify which term (class, object, attribute or method) each of the following is: (a) Book itself; (b) hobbit; (c) hobbit.title; (d) hobbit.describe().

(a: class - the blueprint. b: object - a specific instance built from the Book blueprint. c: attribute - a piece of data belonging to hobbit specifically. d: method - a function belonging to the Book class, called on a specific object.)

Debug it — diagnose, explain, fix, test, justify

class Book:
    def __init__(self, title, author):
        self.title = title
        available = True   # intended as an attribute

    def describe(self):
        status = "available" if self.available else "on loan"
        return f"{self.title} ({status})"

hobbit = Book("The Hobbit", "Tolkien")
print(hobbit.describe())

This crashes with AttributeError: 'Book' object has no attribute 'available', even though available is clearly set in __init__.

  1. Diagnose: is available genuinely being set as an attribute of the object, or is it something else?
  2. Explain: what's the actual difference between available = True and self.available = True inside __init__?
  3. Fix: correct the constructor so available genuinely becomes an attribute of the object.
  4. Test: confirm hobbit.describe() now returns "The Hobbit (available)".
  5. Justify: explain why this exact mistake wouldn't cause an error message inside __init__ itself, only later, in describe.

(available = True (without self.) creates an ordinary local variable that exists only for the duration of the init call - it is never attached to the object at all, and is discarded the moment init returns, exactly like any other local variable and its stack frame from Sequence 10. The fix is self.available = True. No error appears inside init because a plain local variable is completely valid there - the mistake only becomes visible later, when describe() tries to access self.available and finds it was never actually stored on the object.)

Common mistake

Confusing a class with an object — a class is the blueprint (Book), never a "thing" that exists on its own in a running program; an object is one specific instance built from it (hobbit). "Create a Book" is meaningless without specifying which book — you always instantiate a specific object, never "the class" itself.

Why this matters for the NEA

Bundling data and behaviour together, and protecting a class's own structure from being accidentally corrupted elsewhere in a program, is exactly the kind of design decision AQA's NEA marking criteria reward when a project's genuine complexity justifies it (Table 1's Group A entry for "complex user-defined use of OOP model") — not because using a class is inherently impressive, but because it's a genuine, appropriate response to the coupling problem the previous lesson identified.

Check your understanding

Two Book objects are created from the same class. Explain why calling .describe() on each one can return two completely different strings, even though both objects were built from identical code. (Each object has its own separate set of attributes, set independently when it was constructed - self inside describe() refers to whichever specific object the method was called on, so each call uses that object's own title/author/is_available, not some shared value.)

Challenge

Design (write the code for) a simple Song class with attributes title, artist and duration_seconds, and a method format_duration() that returns the duration as a "m:ss" string (e.g. 245 seconds → "4:05").

Looking ahead: the next lesson builds the Book class introduced here out properly — more attributes, more methods, and multiple independent objects whose state changes separately from one another.

Practise

Apply what you've just learned in the Coding Lab.

Open Coding Lab

Test yourself

Check your understanding with exam-style questions.

Go to Exam Practice
Log in to track this lesson on your progress dashboard.
Log in