Classes and Objects
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.
What is a Class?
Section titled “What is a Class?”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.
Real-World Analogy
Section titled “Real-World Analogy”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.
Basic Class Structure
Section titled “Basic Class Structure”Here’s the simplest class definition:
class Dog: pass # Empty class
# Create an instance (object)my_dog = Dog()print(type(my_dog)) # <class '__main__.Dog'><class '__main__.Dog'>public class Dog { // Empty class}
// Create an instance (object)public class Main { public static void main(String[] args) { Dog myDog = new Dog(); System.out.println(myDog.getClass().getName()); // Dog }}DogThe Constructor
Section titled “The Constructor”The constructor is a special method called when you create a new instance of a class.
class Dog: def __init__(self, name: str, breed: str): """Constructor - called when creating a new Dog instance""" self.name = name self.breed = breed
# Create instancesdog1 = Dog("Buddy", "Golden Retriever")dog2 = Dog("Max", "German Shepherd")
print(dog1.name) # "Buddy"print(dog2.breed) # "German Shepherd"BuddyGerman Shepherdpublic class Dog { private String name; private String breed;
// Constructor - called when creating a new Dog instance public Dog(String name, String breed) { this.name = name; this.breed = breed; }
// Getters public String getName() { return name; }
public String getBreed() { return breed; }}
// Create instancespublic class Main { public static void main(String[] args) { Dog dog1 = new Dog("Buddy", "Golden Retriever"); Dog dog2 = new Dog("Max", "German Shepherd");
System.out.println(dog1.getName()); // "Buddy" System.out.println(dog2.getBreed()); // "German Shepherd" }}BuddyGerman ShepherdUnderstanding self and this
Section titled “Understanding self and this”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"Hi, I'm Alice and I'm 30 years oldpublic class Person { private String name; private int age;
// Constructor - this refers to the current instance public Person(String name, int age) { this.name = name; // Instance attribute this.age = age; // Instance attribute }
public String introduce() { // this allows access to instance attributes return "Hi, I'm " + this.name + " and I'm " + this.age + " years old"; }}
// Usagepublic class Main { public static void main(String[] args) { Person person = new Person("Alice", 30); System.out.println(person.introduce()); // "Hi, I'm Alice and I'm 30 years old" }}Hi, I'm Alice and I'm 30 years oldInstance Attributes
Section titled “Instance Attributes”Instance attributes are variables that belong to a specific instance. Each object has its own copy of these attributes.
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 balanceaccount1 = BankAccount("ACC-001", 1000.0)account2 = BankAccount("ACC-002", 500.0)
print(account1.balance) # 1000.0print(account2.balance) # 500.01000.0500.0public class BankAccount { private String accountNumber; private double balance;
// Constructor public BankAccount(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; }
// Getters public double getBalance() { return balance; }
public String getAccountNumber() { return accountNumber; }}
// Usagepublic class Main { public static void main(String[] args) { BankAccount account1 = new BankAccount("ACC-001", 1000.0); BankAccount account2 = new BankAccount("ACC-002", 500.0);
System.out.println(account1.getBalance()); // 1000.0 System.out.println(account2.getBalance()); // 500.0 }}1000.0500.0Instance Methods
Section titled “Instance Methods”Instance methods are functions defined inside a class that operate on instance data.
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
# Usageaccount = BankAccount("ACC-001", 1000.0)print(account.deposit(500.0)) # Deposited $500.00. New balance: $1500.00print(account.withdraw(200.0)) # Withdrew $200.00. New balance: $1300.00print(account.get_balance()) # 1300.0Deposited $500.00. New balance: $1500.00Withdrew $200.00. New balance: $1300.001300.0public class BankAccount { private String accountNumber; private double balance;
public BankAccount(String accountNumber, double balance) { this.accountNumber = accountNumber; this.balance = balance; }
// Instance method - operates on this account public String deposit(double amount) { if (amount > 0) { this.balance += amount; return String.format("Deposited $%.2f. New balance: $%.2f", amount, this.balance); } return "Invalid deposit amount"; }
// Instance method - operates on this account public String withdraw(double amount) { if (amount > 0 && amount <= this.balance) { this.balance -= amount; return String.format("Withdrew $%.2f. New balance: $%.2f", amount, this.balance); } return "Insufficient funds or invalid amount"; }
// Instance method - returns this account's balance public double getBalance() { return this.balance; }}
// Usagepublic class Main { public static void main(String[] args) { BankAccount account = new BankAccount("ACC-001", 1000.0); System.out.println(account.deposit(500.0)); // Deposited $500.00. New balance: $1500.00 System.out.println(account.withdraw(200.0)); // Withdrew $200.00. New balance: $1300.00 System.out.println(account.getBalance()); // 1300.0 }}Deposited $500.00. New balance: $1500.00Withdrew $200.00. New balance: $1300.001300.0Complete Example: User Class
Section titled “Complete Example: User Class”Let’s put it all together with a complete example:
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 instancesuser1 = User("alice", "alice@example.com", 25)user2 = User("bob", "bob@example.com", 30)
# Each user is independentprint(user1.get_info())print(user2.get_info())
# Modify one user - doesn't affect the otheruser1.deactivate()print(user1.get_info())print(user2.get_info())User: alice (alice@example.com), Age: 25, Status: activeUser: bob (bob@example.com), Age: 30, Status: activeUser: alice (alice@example.com), Age: 25, Status: inactiveUser: bob (bob@example.com), Age: 30, Status: activepublic class User { private String username; private String email; private int age; private boolean isActive;
// Constructor - initialize user attributes public User(String username, String email, int age) { this.username = username; this.email = email; this.age = age; this.isActive = true; // Default value }
// Instance method - return user information public String getInfo() { String status = isActive ? "active" : "inactive"; return String.format("User: %s (%s), Age: %d, Status: %s", username, email, age, status); }
// Instance method - deactivate user account public String deactivate() { this.isActive = false; return username + " has been deactivated"; }
// Instance method - activate user account public String activate() { this.isActive = true; return username + " has been activated"; }
// Instance method - update user email public String updateEmail(String newEmail) { if (newEmail.contains("@")) { this.email = newEmail; return "Email updated to " + newEmail; } return "Invalid email address"; }}
// Usagepublic class Main { public static void main(String[] args) { User user1 = new User("alice", "alice@example.com", 25); User user2 = new User("bob", "bob@example.com", 30);
// Each user is independent System.out.println(user1.getInfo()); System.out.println(user2.getInfo());
// Modify one user - doesn't affect the other user1.deactivate(); System.out.println(user1.getInfo()); System.out.println(user2.getInfo()); }}User: alice (alice@example.com), Age: 25, Status: activeUser: bob (bob@example.com), Age: 30, Status: activeUser: alice (alice@example.com), Age: 25, Status: inactiveUser: bob (bob@example.com), Age: 30, Status: activeclassDiagram
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"
Visual Representation
Section titled “Visual Representation”Key Takeaways
Section titled “Key Takeaways”Next Steps
Section titled “Next Steps”Now that you understand the basics of classes, you’re ready to explore:
- Enums - Named constants and type-safe enumerations
- Interfaces - Contracts that classes can implement
- Encapsulation - Protecting data with access modifiers
- Abstraction - Hiding complexity and exposing essential features
- Inheritance - Creating class hierarchies
- Polymorphism - Using objects interchangeably
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.