Skip to content
Low Level Design Mastery Logo
LowLevelDesign Mastery

Classes and Objects

Learn the fundamentals of creating and using classes

Before diving into advanced OOP concepts, let’s start with the fundamentals: understanding what classes are and how to write them in Python and Java.

A class is a blueprint or template for creating objects. It defines:

  • Attributes (data/variables)
  • Methods (functions that operate on the data)

An object (or instance) is a specific realization of a class - a concrete example created from the blueprint.

Think of a class like a cookie cutter:

  • The class is the cookie cutter (the template)
  • The objects are the cookies (specific instances created from the template)

All cookies made from the same cutter have the same shape, but each cookie is a separate object.

Here’s the simplest class definition:

simple_class.py
class Dog:
pass # Empty class
# Create an instance (object)
my_dog = Dog()
print(type(my_dog)) # <class '__main__.Dog'>
Output
<class '__main__.Dog'>

The constructor is a special method called when you create a new instance of a class.

init_method.py
class Dog:
def __init__(self, name: str, breed: str):
"""Constructor - called when creating a new Dog instance"""
self.name = name
self.breed = breed
# Create instances
dog1 = Dog("Buddy", "Golden Retriever")
dog2 = Dog("Max", "German Shepherd")
print(dog1.name) # "Buddy"
print(dog2.breed) # "German Shepherd"
Output
Buddy
German Shepherd
understanding_self.py
class Person:
def __init__(self, name: str, age: int):
# self refers to the current instance
self.name = name # Instance attribute
self.age = age # Instance attribute
def introduce(self):
# self allows access to instance attributes
return f"Hi, I'm {self.name} and I'm {self.age} years old"
person = Person("Alice", 30)
print(person.introduce()) # "Hi, I'm Alice and I'm 30 years old"
Output
Hi, I'm Alice and I'm 30 years old

Instance attributes are variables that belong to a specific instance. Each object has its own copy of these attributes.

instance_attributes.py
class BankAccount:
def __init__(self, account_number: str, balance: float):
# Instance attributes - unique to each account
self.account_number = account_number
self.balance = balance
# Each account has its own balance
account1 = BankAccount("ACC-001", 1000.0)
account2 = BankAccount("ACC-002", 500.0)
print(account1.balance) # 1000.0
print(account2.balance) # 500.0
Output
1000.0
500.0

Instance methods are functions defined inside a class that operate on instance data.

instance_methods.py
class BankAccount:
def __init__(self, account_number: str, balance: float):
self.account_number = account_number
self.balance = balance
def deposit(self, amount: float):
"""Instance method - operates on this account"""
if amount > 0:
self.balance += amount
return f"Deposited ${amount:.2f}. New balance: ${self.balance:.2f}"
return "Invalid deposit amount"
def withdraw(self, amount: float):
"""Instance method - operates on this account"""
if 0 < amount <= self.balance:
self.balance -= amount
return f"Withdrew ${amount:.2f}. New balance: ${self.balance:.2f}"
return "Insufficient funds or invalid amount"
def get_balance(self):
"""Instance method - returns this account's balance"""
return self.balance
# Usage
account = BankAccount("ACC-001", 1000.0)
print(account.deposit(500.0)) # Deposited $500.00. New balance: $1500.00
print(account.withdraw(200.0)) # Withdrew $200.00. New balance: $1300.00
print(account.get_balance()) # 1300.0
Output
Deposited $500.00. New balance: $1500.00
Withdrew $200.00. New balance: $1300.00
1300.0

Let’s put it all together with a complete example:

user_class.py
class User:
"""A simple User class demonstrating basic OOP concepts"""
def __init__(self, username: str, email: str, age: int):
"""Constructor - initialize user attributes"""
self.username = username
self.email = email
self.age = age
self.is_active = True # Default value
def get_info(self):
"""Instance method - return user information"""
status = "active" if self.is_active else "inactive"
return f"User: {self.username} ({self.email}), Age: {self.age}, Status: {status}"
def deactivate(self):
"""Instance method - deactivate user account"""
self.is_active = False
return f"{self.username} has been deactivated"
def activate(self):
"""Instance method - activate user account"""
self.is_active = True
return f"{self.username} has been activated"
def update_email(self, new_email: str):
"""Instance method - update user email"""
if "@" in new_email:
self.email = new_email
return f"Email updated to {new_email}"
return "Invalid email address"
# Create user instances
user1 = User("alice", "alice@example.com", 25)
user2 = User("bob", "bob@example.com", 30)
# Each user is independent
print(user1.get_info())
print(user2.get_info())
# Modify one user - doesn't affect the other
user1.deactivate()
print(user1.get_info())
print(user2.get_info())
Output
User: alice (alice@example.com), Age: 25, Status: active
User: bob (bob@example.com), Age: 30, Status: active
User: alice (alice@example.com), Age: 25, Status: inactive
User: bob (bob@example.com), Age: 30, Status: active
classDiagram
    class User {
        -username: str
        -email: str
        -age: int
        -is_active: bool
        +__init__(username, email, age)
        +get_info() str
        +deactivate() str
        +activate() str
        +update_email(new_email) str
    }
    
    note for User "Class: Blueprint\nInstance: Specific user"
Diagram

Now that you understand the basics of classes, you’re ready to explore:

Remember: Classes are a way to model real-world entities in code, bundling together related data (attributes) and behavior (methods) into a single, reusable unit.