Skip to content
FollowtheDamnCode

Classes and Objects

A class is a blueprint for data plus the behaviour that keeps it valid; an object is one live instance of it.

Big idea

A class bundles data with the operations that are allowed to change it, and an object is one instance with its own copy of that data. Everything else in this track — every principle, every pattern — is a decision about which data lives together and who is allowed to touch it.

The problem it solves

Picture a program that tracks bank accounts with loose variables and free functions: a dictionary for balances, another for owners, a withdraw(balances, id, amount) function somewhere, and a second copy of the overdraft rule pasted into the transfer code. Nothing stops a careless line from setting a balance to -500, and nothing tells a reader which functions belong to "an account".

A class draws a boundary: here is an account; here are the only ways to change one. The rule against overdrafts lives in exactly one place, next to the balance it protects.

Think of it like

A cookie cutter and the cookies it stamps out. The cutter (the class) is the shape — it isn't food, and you only need one. Each cookie (an object) has the same shape but its own icing, its own bite taken out of it. Decorating one cookie doesn't change the others, and nobody confuses the cutter with lunch.

The pieces

  • Attributes (fields, state) — the data each object carries: owner, balance.
  • Methods — functions that run on an object and can read and change its attributes: deposit(), withdraw().
  • Constructor (__init__ in Python) — runs once when an object is created and puts it into a valid starting state.
  • Instance vs class members — self.balance belongs to one object; a class attribute such as Account.interest_rate is shared by all of them.
  • Identity vs equality — two accounts with the same owner and balance are equal-looking but still two different objects; changing one doesn't change the other.
One class, two objects

In UML class diagrams, + marks something public and - something private; you'll see these boxes in every lesson that follows.

In code

An account that refuses to go negative
class Account:
    interest_rate = 0.02          # class attribute: shared by every account

    def __init__(self, owner, balance=0):
        self.owner = owner        # instance attributes: one copy per object
        self._balance = balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("deposit must be positive")
        self._balance += amount

    def withdraw(self, amount):
        if amount > self._balance:
            return False          # the rule lives here, once
        self._balance -= amount
        return True

    def get_balance(self):
        return self._balance


asha = Account("Asha", 100)
ben = Account("Ben", 40)
asha.deposit(20)
print(asha.owner, asha.get_balance())
print("Ben withdraws 50:", ben.withdraw(50))
print(ben.owner, ben.get_balance())

twin = Account("Asha", 120)
print("same data:", twin.get_balance() == asha.get_balance())
print("same object:", twin is asha)
print("shared rate:", asha.interest_rate, ben.interest_rate)
output
Asha 120
Ben withdraws 50: False
Ben 40
same data: True
same object: False
shared rate: 0.02 0.02

Run and edit it in the app.

twin and asha hold the same values but are different objects — is checks identity, == on the balances checks values.

You create three Account objects from one Account class and deposit into the first. What happens to the other two?

Watch it

When to reach for a class — and when not to

Use a class when some data has rules (a balance can't go negative, a date must be valid), when several operations act on the same data, or when you'll want many independent copies of the same kind of thing.

Don't wrap everything in a class. A pure calculation — celsius_to_fahrenheit(c) — is clearer as a plain function. A record with no rules is often clearer as a plain data class or named tuple. A class with one method and no state is usually a function wearing a costume.

Pros and cons

ProsCons
Rules sit next to the data they protectEasy to over-model: classes for things that are just data
Many independent instances for freeHidden state can make behaviour depend on call order
A shared vocabulary (Account, Order) for the teamDeep class trees get hard to follow (see Inheritance vs Composition)

How it relates

  • Encapsulation is the discipline that makes the boundary real — hiding _balance so the rule can't be bypassed.
  • Coupling and Cohesion gives you the test for which data belongs in the same class.
  • Every pattern in this track is a recipe for arranging classes and objects; the LLD case studies start by finding them in a requirements list.

a = Account('Asha', 120) and b = Account('Asha', 120). Which is true?

Key terms

  • Class — A blueprint that defines what data an object holds and which methods operate on it.
  • Object (instance) — One concrete thing built from a class, with its own copy of the instance data.
  • Attribute — A piece of data stored on an object (or on the class, if shared).
  • Method — A function defined in a class that runs on a particular object, reached through self.
  • Constructor — The method that runs when an object is created and sets up a valid initial state.