You have now mastered breaking down complex problems into smaller, more manageable modules with functions and organizing your code in multiple files as modules and packages for enhanced reusability. Although these are handy tools for creating robust applications, as your system grows in complexity, the procedural (step-by-step) approach becomes difficult to maintain and manage.
So, we use a new (for you), more advanced approach called Object-Oriented Programming (OOP). This programming paradigm allows you to treat everything as an object with some properties and behaviors. We model real-world entities and their interactions in our code, ultimately leading to better code organization, more reusability, and better maintenance. The two core concepts of OOP are the classes and objects that we will explore in this article. It’s going to be fun, so stay tuned. But please remember that these concepts are really important for building highly sophisticated and efficient applications.
Understanding Object-Oriented Programming – Core Concepts
Paradigm
A programming paradigm is simply a way of organizing the structure and execution of a program. So far, we have been using the Procedural Programming paradigm, and now, it’s time to get started with the Object-Oriented programming paradigm.
Core Pillars of OOP
OOP is based on the following 4 core pillars:
- Encapsulation: Combining data and functions that work on that data into a single unit.
- Inheritance: Deriving one class from other existing classes and providing them their own entities as well.
- Polymorphism: Having multiple shapes of a single entity.
- Abstraction: Hiding complex program logic from the end user and providing them access to only the necessary details.
Benefits of OOP
- OOP allows you to break down complex logic into smaller, self-contained objects to achieve modularity.
- The classes and objects can be used in different parts of a program or entirely different programs (reusability).
- Making changes to one part of the system does not affect the other components (Maintainability).
- You can easily extend the existing code without modifying it (code flexibility).
Introduction to Classes
A class is a blueprint, prototype, or template of an object. It defines the characteristics (data or attributes) and behaviors (functions or methods) of the object. A class itself does not have any physical existence, nor does its data items occupy any memory unless an object has been created from it. Any object created from a particular class possesses all the attributes and behaviors defined within a class.
To understand this, consider that you want to build a mall in some area. Before building the actual building, you will ask an architect to create a blueprint/map or a design for the building, which would be either on paper or computer. So, that blueprint will be considered as the class unless the building has not been built. Similarly, the human being is an idea or a class that has some properties, say eyes, nose, hands, and feet, and each of these properties has different functions, say eyes are to see, the nose is to smell, hands are to touch, and feet are to walk and so on. So, all of this is just a blueprint unless an actual human being has not formed.
If you look around you, you will find that everything has a class. A hen belongs to the Birds class, and a dog belongs to the Animals class, a rose belongs to the Flower class.
Defining a Class
Syntax:
class class_name:
#attributes
#methods
Example:
class Box: # A class with 2 attributes
width = 10
height = 10
The Constructor (__init__ Method)
The __init__
method in Python represents the constructor. A constructor is simply a method that is used to initialize the class data when an object is created. A constructor can have parameters. An important parameter that is recommended to use in every constructor is self
. This parameter refers to the current instance of the class.
Syntax:
class class_name:
attributes
def __init__(self, parameter):
constructor_body
Example:
class Box: # A class with 2 attributes
width = 10
height = 10
def __init__(self, w, h):
self.width = w # Assigns the new width to the width attribute of the current object
self.height = h # Assigns the new height to the height attribute of the current object
The Methods – Behaviors of a Class
The methods are simply the functions defined within a class. They are defined with the same syntax as a general function.
Syntax:
class class_name:
#attributes
#def function_name(parameters):
function_body
Example:
class Box: # A class with 2 attributes
width = 10
height = 10
def __init__(self, w, h):
self.width = w # Assigns the new width to the width attribute of the current object
self.height = h # Assigns the new height to the height attribute of the current object
def dimensions(self): # Prints the dimensions of the box on the screen
print("The dimensions are ", self.width, " x ", self.height)
square = Box(20, 20) #Assigns 20 to both width and height attributes of the square object.
rectangle = Box(30, 50) # Another object with different values
square.dimensions()
rectangle.dimensions()
Introduction to Objects – The Instance of a Class
An object is an instance of a class. It is the actual implementation of the idea defined within a class. It possesses all the attributes and behaviors defined within the class definition. Each object has a separate copy of these attributes.
Creating an Object
Syntax:
object_name = class_name()
Please note that you may need to pass some values to the constructor while calling the class if required.
object_name = class_name(values)
Example:
class Box: # A class with 2 attributes
width = 10
height = 10
def __init__(self, w, h):
self.width = w # Assigns the new width to the width attribute of the current object
self.height = h # Assigns the new height to the height attribute of the current object
square = Box(20, 20) #Assigns 20 to both width and height attributes of the square object.
print("Width: ", square.width)
print("Height: ", square.height)
Output:
Width: 20
Height: 20
Example 2:
The following example shows how different objects have separate copies of attributes:
class Box: # A class with 2 attributes
width = 10
height = 10
def __init__(self, w, h):
self.width = w # Assigns the new width to the width attribute of the current object
self.height = h # Assigns the new height to the height attribute of the current object
def dimensions(self): # Prints the dimensions of the box on the screen
print("The dimensions are ", self.width, " x ", self.height)
square = Box(20, 20) #Assigns 20 to both width and height attributes of the square object.
rectangle = Box(30, 50) # Another object with different values
print("Width: ", square.width) #Accessing attributes
print("Height: ", square.height)
rectangle.dimensions() #Accessing member method
Output:
Width: 20
Height: 20
The dimensions are 30 x 50
Accessing Member Attributes and Methods
We can access attributes of an object with dot notation:
Syntax:
object_name.attribute
Example:
rectangle.height
rectangle.dimensions()
You have taken a monumental step into the world of object-oriented programming. You can now differentiate between the classes and the objects. I recommend that you spend as much time as you can practicing these concepts. In the next article, we will cover Inheritance and Polymorphism.