Introduction
In this article, we will build the OOP version of the Coffee Machine in Python.
What is OOP?
Object Oriented Programming is a programming concept that is based on creating Classes and Objects. In simple words, a Class is a template or a blueprint, a defined broad category, and Objects are the individual structures that are created from these Classes. The Class in OOP defines certain features that all the objects that come from this class will have, these are called the Attributes. Moreover, the Class also defined certain functions that it can do. In OOP terminology, these are called Methods.
Suppose we define a class “Cats”. This is a broad category and will include all types of cats as its objects: my cat Figaro, the neighbor’s cat Simba, etc. Each cat will have some individual characteristics like their name, eye color, their breed, etc. These will be coded as their attributes. Moreover, they will also have specific functions like being able to hunt, sleep, play, meow, etc. These will be coded as their methods.
The following is how classes and objects are coded:
class Cat:
def __init__(self, name, eye_color, fur_color, breed, age, length):
self.name = name
self.eye_color = age
self.fur_color = fur_color
self.breed = breed
self.age = age
self.length = length
def hunt(self, animal):
print(f"My cat {self.name} is hunting a {animal}")
my_cat = Cat("Figaro", "blue", "black and white", "Persian", "2", "48")
print(my_cat.name)
neighbour_cat = Cat("Simba", "hazel", "brown", "Siamese", "3", "50")
neighbour_cat.hunt("mouse")

We will use the above concept and functionality to build an OOP version of a coffee machine.
Project Working
In my previous article on the Coffee Machine, I thoroughly explained the working of the project. This project will be similar in its working, except that we will utilize Object-Oriented Programming to achieve the same results. Overall, we have the following steps:

Defining Classes for our Coffee Machine
The first step in this project is to define our classes, one by one, and then we are going to use these blueprints to define objects needed throughout the project.
Defining the “MenuItem” Class
First of all we will define the MenuItem class, that will model each item in our menu, and will use the objects created from it in the next class we will create Menu.
class MenuItem:
def __init__(self, name, water, milk, coffee, cost):
self.name = name
self.cost = cost
self.ingredients = {
"water": water,
"milk": milk,
"coffee": coffee
}
Suppose we want to create an object menuitem of the class MenuItem. In that case, we will need to give it the following parameters: name of the item, the amount of water required to make this menu item, the amount of milk required to make this menu item, the amount of coffee required to make this menu item, and the cost of this menu item.

This MeniItem class will be used to initialize objects later on.
Defining the “Menu” Class
Next, let us define a class Menu that will contain the details of each item that can be ordered. The object menu can be initialized with the constructor below, and the menu attribute of this class will be a list of the 3 items constructed as objects from the class we constructed earlier MenuItem. We will construct 3 objects from this class with their defined parameters. So, for example, the object latte will require 200 ml of water, 150ml of milk, and 24 g of coffee, and the cost will be $2.5. All this will be modeled inside the class constructor of Menu, which will be used to initialize objects of this class. The __init__ method is always called whenever we create an object.
class Menu:
def __init__(self):
self.menu = [
MenuItem(name="latte", water=200, milk=150, coffee=24, cost=2.5),
MenuItem(name="espresso", water=50, milk=0, coffee=18, cost=1.5),
MenuItem(name="cappuccino", water=250, milk=50, coffee=24, cost=3),
]
Now we have the Menu attributes, we will also define two methods in it. One is to return the names of the available menu items get_items, and the second method find_drink, is to find the drink that the user selects through the input function.
class Menu:
...
def get_items(self):
options = ""
for item in self.menu:
options += f"{item.name}/"
return options
def find_drink(self, order_name):
for item in self.menu:
if item.name == order_name:
return item
print("Sorry that item is not available.")
Creating an Object from the “Menu” Class
To put this class and its associated attributes and methods to use, we will first initialize an object menu of the class Menu. We will then use the method get_items to display to the user the items we have in our menu.
menu = Menu()
drinks = menu.get_items()
drink_selected = input(f"Select your drink {drinks}: ")
menu.find_drink(drink_selected)
Once the user has typed their drink, we will check if it is present in the menu object using the Menu class find_drink method. This method checks if the user input is present in the menu, it will return that item, otherwise it will print out to the user that the drink is not available.

So if we give an order of a vanilla shake, the program will simply print out that the item is not available. When the input drink is present in our defined menu, the method find_drink will return the item. Now we can use this item in our coding ahead.
Defining the “CoffeeMaker” Class
Our next step is to define the CoffeeMaker class. The CoffeeMaker class will store the resources specified beforehand, and will have 3 methods that their objects can be used:
reportmethod : This method will allow the management to check the resources in the coffee machine by printing a report of all resources.is_resources_sufficientmethod: This method will check if the resources in the coffee machine are sufficient to make the desired drink. It will returnTrueif resources are sufficient; otherwise will let the user know which resource is insufficient.make_coffeemethod: The last method will be called when the program’s requirements have been fulfilled, and we have to make the coffee. This piece of code will deduct the resources and dispense coffee.
class CoffeeMaker:
def __init__(self):
self.resources = {
"water": 1000,
"milk": 1000,
"coffee": 200,
}
def report(self):
print(f"Water: {self.resources['water']}ml")
print(f"Milk: {self.resources['milk']}ml")
print(f"Coffee: {self.resources['coffee']}g")
def is_resource_sufficient(self, drink):
can_make = True
for item in drink.ingredients:
if drink.ingredients[item] > self.resources[item]:
print(f"Sorry there is not enough {item}.")
can_make = False
return can_make
def make_coffee(self, order):
for item in order.ingredients:
self.resources[item] -= order.ingredients[item]
print(f"Here is your {order.name} ☕️. Enjoy!")
Defining the “MoneyMachine” Class
Lastly, let us also define the class MoneyMachine. This class will be responsible for the money management. It will process coins to check if payment is made and add the money received to the money bank.
The MoneyMachine class has the following methods:
reportmethod: This method will print how much money we have in our accountprocess_coinsmethod: This method will process the payment in the form of coins of nickels, dimes, quarters, and pennies and will calculate the total.make_paymentmethod : This method will be used to check if the payment is made, is it complete or if the user has overpaid; it will return the change.
class MoneyMachine:
CURRENCY = "$"
COIN_VALUES = {
"quarters": 0.25,
"dimes": 0.10,
"nickles": 0.05,
"pennies": 0.01
}
def __init__(self):
self.profit = 0
self.money_received = 0
def report(self):
print(f"Money: {self.CURRENCY}{self.profit}")
def process_coins(self):
"Please insert coins.")
for coin in self.COIN_VALUES:
self.money_received += int(input(f"How many {coin}?: ")) * self.COIN_VALUES[coin]
return self.money_received
def make_payment(self, cost):
self.process_coins()
if self.money_received >= cost:
change = round(self.money_received - cost, 2)
print(f"Here is {self.CURRENCY}{change} in change.")
self.profit += cost
self.money_received = 0
return True
else:
print("Sorry that's not enough money. Money refunded.")
self.money_received = 0
return False
The Final Code
Now that we have defined our classes, we will write the final code that will ask the user for their order, check that resources are sufficient, process the coins and payments and dispense the drinks when conditions are satisfied. All this will be done by initializing objects.
money_machine = MoneyMachine()
coffee_maker = CoffeeMaker()
menu = Menu()
is_on = True
while is_on:
options = menu.get_items()
choice = input(f"What would you like {options}: ")
if choice == 'off':
is_on = False
elif choice == 'report':
coffee_maker.report()
money_machine.report()
else:
drink = menu.find_drink(choice)
if coffee_maker.is_resource_sufficient(drink) and money_machine.make_payment(drink.cost):
coffee_maker.make_coffee(drink)
In our final code, we have created a while loop that runs continuously unless someone from management commands it to stop. We have done this using the is_on boolean variable, which changes to False when the management types “off” as input to the order prompt.
Moreover, just like we did in our coffee machine project without OOP, we have also added the report option that gives report of all the resources in the coffee machine, and the money in the account
The program will run as follows: It will prompt the user to order a drink by displaying the menu items. If the item selected by the user is in the list, it will first check if resources are sufficient, then ask for payment and check if the payment is complete, and then process the order. All this has been done using OOP concepts of classes and objects.
Conclusion
While we have not fully explored the capabilities of OOP in this project, we have successfully decreased our lines of code by introducing classes and creating objects from them. When it comes to more complex projects with a number of different objects, all sharing a common blueprint, the inclusion of OOP concepts come in way more handy.
Nevertheless, this coffee machine project using OOP has been a useful tutorial to grasp the basics of Object Oriented Programming. If you have any suggestions or can think of an alternative flow of tasks for this project, feel free to share. Till then, enjoy your coffee! 😀






