Chapter 8: OOP in Practice
In this chapter, we will put theory into practice by building three different projects using Object-Oriented Programming (OOP) principles. By designing a simple game, a basic e-commerce system, and a library management system, you will gain a clearer understanding of how OOP concepts can be applied to solve real-world problems.
1. Building a Simple Game Using OOP Principles
Let’s create a simple text-based game where a player can battle monsters. We’ll use OOP concepts to structure the game and represent the characters, actions, and game logic.
Step 1: Define the Character class
Every player and monster in the game can be considered a character, so we’ll create a base class to hold common attributes and methods.
class Character:
def __init__(self, name, health, attack_power):
self.name = name
self.health = health
self.attack_power = attack_power
def attack(self, other):
other.health -= self.attack_power
print(f"{self.name} attacks {other.name} for {self.attack_power} damage!")
Step 2: Define the Player and Monster classes
We can extend the Character class to create specific types of characters, such as players and monsters.
class Player(Character):
def heal(self):
self.health += 10
print(f"{self.name} heals and gains 10 health points.")
class Monster(Character):
def roar(self):
print(f"{self.name} roars menacingly!")
Step 3: Game Logic
Let’s now create the main game loop where the player battles a monster.
def battle(player, monster):
while player.health > 0 and monster.health > 0:
player.attack(monster)
if monster.health <= 0:
print(f"{monster.name} has been defeated!")
break
monster.attack(player)
if player.health <= 0:
print(f"{player.name} has been defeated!")
break
# Create a player and monster
player = Player(name="Hero", health=100, attack_power=20)
monster = Monster(name="Goblin", health=50, attack_power=15)
# Start the battle
battle(player, monster)
OOP Concepts Used:
- Encapsulation: The character’s health and attack power are encapsulated within the
Characterclass. - Inheritance: The
PlayerandMonsterclasses inherit from theCharacterclass. - Polymorphism: Both
PlayerandMonsterclasses use theattack()method, but they behave according to their unique attributes.
2. Designing a Basic E-commerce System
In this section, we’ll build a simple e-commerce system where users can browse products, add them to a cart, and complete a purchase.
Step 1: Define the Product class
A product has attributes such as name, price, and stock. These will be encapsulated in the Product class.
class Product:
def __init__(self, name, price, stock):
self.name = name
self.price = price
self.stock = stock
def update_stock(self, quantity):
self.stock -= quantity
print(f"{quantity} units of {self.name} sold. Stock left: {self.stock}")
Step 2: Define the Cart class
A cart will store products that the user adds. It will also calculate the total price of the products in the cart.
class Cart:
def __init__(self):
self.items = []
def add_to_cart(self, product, quantity):
if product.stock >= quantity:
self.items.append((product, quantity))
product.update_stock(quantity)
else:
print(f"Not enough stock for {product.name}.")
def calculate_total(self):
total = sum(product.price * quantity for product, quantity in self.items)
print(f"Total: ${total}")
return total
Step 3: Define the User class
The user will interact with the e-commerce system by browsing products and adding them to the cart.
class User:
def __init__(self, name):
self.name = name
self.cart = Cart()
def purchase(self):
total = self.cart.calculate_total()
print(f"{self.name} has purchased items worth ${total}.")
Step 4: Create Products and Simulate a Purchase
Let’s create a few products, add them to a user’s cart, and simulate a purchase.
# Create some products
product1 = Product("Laptop", 1000, 10)
product2 = Product("Smartphone", 500, 20)
# Create a user
user = User("Alice")
# User adds products to the cart
user.cart.add_to_cart(product1, 1)
user.cart.add_to_cart(product2, 2)
# User completes the purchase
user.purchase()
OOP Concepts Used:
- Encapsulation: The product’s details (name, price, stock) are encapsulated within the
Productclass. - Abstraction: The user does not need to know how the total is calculated; they just use the
purchase()method. - Modularity: Each part of the system (Product, Cart, User) is separated into its own class, making the system easier to maintain and extend.
3. Creating a Library Management System
In this example, we’ll create a system that manages a library’s books, borrowers, and loan processes.
Step 1: Define the Book class
The Book class will store information about the book, such as title, author, and availability.
class Book:
def __init__(self, title, author, available=True):
self.title = title
self.author = author
self.available = available
def borrow(self):
if self.available:
self.available = False
print(f"{self.title} has been borrowed.")
else:
print(f"{self.title} is currently unavailable.")
def return_book(self):
self.available = True
print(f"{self.title} has been returned.")
Step 2: Define the Borrower class
The borrower class will represent users who can borrow and return books.
class Borrower:
def __init__(self, name):
self.name = name
self.borrowed_books = []
def borrow_book(self, book):
if book.available:
book.borrow()
self.borrowed_books.append(book)
else:
print(f"{self.name} cannot borrow {book.title}.")
def return_book(self, book):
if book in self.borrowed_books:
book.return_book()
self.borrowed_books.remove(book)
else:
print(f"{self.name} does not have {book.title}.")
Step 3: Manage the Library
Let’s create a simple library system where users can borrow and return books.
# Create some books
book1 = Book("1984", "George Orwell")
book2 = Book("The Great Gatsby", "F. Scott Fitzgerald")
# Create a borrower
borrower = Borrower("John")
# Borrow and return books
borrower.borrow_book(book1)
borrower.return_book(book1)
borrower.borrow_book(book2)
OOP Concepts Used:
- Encapsulation: Each book’s availability and details are encapsulated within the
Bookclass. - Abstraction: Borrowers interact with books through simple methods like
borrow()andreturn_book(), without needing to understand the inner workings. - Inheritance: Could be used in a more complex system, for example, creating specialized
ReferenceBookandFictionBookclasses.