Skip to main content

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 Character class.
  • Inheritance: The Player and Monster classes inherit from the Character class.
  • Polymorphism: Both Player and Monster classes use the attack() 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 Product class.
  • 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 Book class.
  • Abstraction: Borrowers interact with books through simple methods like borrow() and return_book(), without needing to understand the inner workings.
  • Inheritance: Could be used in a more complex system, for example, creating specialized ReferenceBook and FictionBook classes.