Thursday, March 17, 2022

Understanding OOP principles

OOP is a way of bundling properties and behavior into a single entity, which we call objects. To make this bundling more efficient and modular, there are several principles available in Python, outlined as follows:

• Encapsulation of data

• Inheritance

• Polymorphism

• Abstraction

We will study each of these principles in detail.

Encapsulation of data

Encapsulation is a fundamental concept in OOP and is also sometimes referred to as abstraction. But in reality, the encapsulation is more than the abstraction. In OOP, bundling of data and the actions associated with the data into a single unit is known as encapsulation. Encapsulation is actually more than just bundling data and the associated actions. We can enumerate three main objectives of encapsulation here, as follows:

• Encompass data and associated actions in a single unit.

• Hide the internal structure and implementation details of the object.

• Restrict access to certain components (attributes or methods) of the object.

Encapsulation simplifies the use of the objects without knowing internal details on how it is implemented, and it also helps to control updates to the state of the object.

Let us discuss these objectives in detail.

Encompassing data and actions

To encompass data and actions in one init, we define attributes and methods in a class. A class in Python can have the following types of elements:

• Constructor and destructor

• Class methods and attributes

• Instance methods and attributes

• Nested classes

We have discussed these class elements already in the previous section, except nested or inner classes. We already provided the Python code examples to illustrate the implementation of constructors and destructors. We have used instance attributes to encapsulate data in our instances or objects. We have also discussed the class methods, static methods, and class attributes with code examples in the previous section.

To complete the topic, we will discuss the following Python code snippet with a nested class. Let's take an example of our Car class and an Engine inner class within it. Every car needs an engine, so it makes sense to make it a nested or inner class:

#carwithinnerexample1.py

class Car:

"""outer class"""

c_mileage_units = "Mi"

def __init__(self, color, miles, eng_size):

self.i_color = color

self.i_mileage = miles

self.i_engine = self.Engine(eng_size)

def __str__(self):

return f"car with color {self.i_color}, mileage \

{self.i_mileage} and engine of {self.i_engine}"

class Engine:

"""inner class"""

def __init__(self, size):

self.i_size = size

def __str__(self):

return self.i_size

if __name__ == "__main__":

car = Car ("blue", 1000, "2.5L")

print(car)

print(car.i_engine.i_size)

In this example, we defined an Engine inner class inside our regular Car class. The Engine class has only one attribute—i_size, the constructor method (__init__), and the __str__ method. For the Car class, we updated the following as compared to our previous examples:

• The __init__ method includes a new attribute for engine size, and a new line has been added to create a new instance of Engine associated with the Car instance.

• The __str__ method of the Car class includes the i_size inner class attributes in it.

The main program is using a print statement on the Car instance and also has a line to print the value of the i_size attribute of the Engine class. The console output of this program will be similar to what is shown here:

car with color blue, mileage 1000 and engine of 2.5L

2.5L

The console output of the main program shows that we have access to the inner class from within the class implementation and we can access the inner class attributes from outside.

In the next post, we will discuss how we can hide some of the attributes and methods to not be accessible or visible from outside the class.

Share:

0 comments:

Post a Comment