The Four Pillars of Object Oriented Programming
The fundamentals of Inheritance, Polymorphism, Abstraction, and Encapsulation in Python

Introduction
In my previous article on Object Oriented Programming I discussed how to create new classes, attributes, and methods using Python. For this article I will now cover the core foundations or pillars of OOP. These four pillars consist of Inheritance, Polymorphism, Abstraction, and Encapsulation. This article will give an overview of the fundamentals of each pillar using examples in Python.
Inheritance
The first pillar of object oriented programming that we will cover is Inheritance. Inheritance can basically be summarized as a way to create new classes based on previously defined classes. This is very useful for re-using code as well as reducing a program’s complexity. Inheritance works by acquiring the attributes and methods of a base or parent class in order to create a new derived or child class. For example in my previous article on object oriented programming we created a user-defined ‘FootballTeams’ class with its own unique attributes and methods as seen below.

Now let’s say we wanted to create a new class for college football teams rather than NFL football teams. We can see that all these attributes and methods would also apply to college teams, so rather than starting from scratch with our code we can simply apply all the attributes and methods from our ‘FootballTeams’ class to our new ‘CollegeFootballTeams’ class. We do this by first writing the ‘class’ keyword before our new class name. We then pass in the class that we want to inherit from and initilize our new class with the same parameters as our previous class, as seen below.

We can create a new instance of our new ‘CollegeFootballTeams’ class and see that it will now posses the same attributes and methods as our ‘FootballTeams’ class after passing in our parameters through the use of Inheritance.

Polymorphism
The second pillar of OOP that we will discuss is Polymorphism. Polymorphism is essentially a way for different object classes to share the same method name, allowing these methods to be called from the same place even though different objects may be passed in. For example when we created the new ‘CollegeFootballTeams’ class above it inherited all the ‘FootballTeams’ class attibutes and methods as previously described. Because of this we are now able to call the same method names even though the class name has changed. For example both the ‘FootballTeams’ class as well as the ‘CollegeFootballTeams’ class can now use the .postseason() method despite being seperate classes, which is possible through polymorphism. We can see an example of this in the function below.

We can see that when we call the .qb_sneak() method and check the class type, even though they are separate classes they both are able to use the same method through polymorphism.
We are also able to override certain methods in our new derived class from our base class. For example if we wanted to change the output of the .postseason() method we do this by simply overwriting the method when creating the derived class as seen below.

Now when we call the .postseason() method on the ‘CollegeFootballTeams’ class it will specify “college playoffs” in the output rather than just “playoffs” in the ‘FootballTeams’ class even though we are still calling the same method on each through the use of Polymorphism.
Abstraction
The next pillar of OOP, Abstaction, is basically hiding the data that you don’t want to the user to see while only showing the necessary details to the user of the object. This greatly helps to separate the user from the underlying implementation, since the user likely only cares about calling the method rather than the details behind it. An example of using an abstract class in Python is creating a base class without the intention of creating an instance of that class, leaving it to serve only as a base class. An example of this would be if we just created our ‘FootballTeams’ class without creating any instances of it such as ‘jets’ and ‘raiders’. Instead of creating a new instance of the abstact class we would instead need to create a derived class from the abstact class as seen in the example below using the ‘abc’ library.

Encapsulation
Finally the fourth and final pillar of OOP is Encapsulation. Encapsulation is basically summarized as bundling data and methods within a single unit in order to prevents unwanted changes and modification of the data. Encapsulation is used mainly for safety and security purposes as well as to restrict certain properties from outside of a class. A basic example of encapsulation is when we created our ‘FootballTeams’ class we wrapped everything into a single unit of code or encapsulated it within the class.
In Python we can also use access modifiers to encapsulate our data. Three examples of access modifiers in Python are: ‘Public Member’, ‘Private Member’, and ‘Protected Member’. We implement these by using a single underscore for ‘Protected Members’ and a double underscore before the variable for ‘Private Members’ that we want to encapsulate. ‘Public Member’ is simply the default data member that we’ve been implementing thus far and is accessible anywhere outside of a class. A ‘Protected Member’ is accessible within the class as well as any instances of the class. Finally a ‘Private Member is accessible only within the class.

In order to access Protected and Private members in Python we would need to use ‘getter’ methods. In order to edit this data we would need to use ‘setter’ methods to ensure proper encapsulation, otherwise we will get an error message when trying to access this encapsulated data.
Conclusion
In summary, Inheritance can be thought of as a way to create new classes based on previously defined classes. Polymorphism is essentially a way for different object classes to share the same method name, allowing these methods to be called from the same place even though different objects may be passed in. Abstraction is hiding the data that you don’t want to the user to see while only showing the necessary details to the user of the object. Finally Encapsulation is the bundling of data and methods within a single unit in order to prevent unwanted changes and modifications of the data. Overall we can start to see how important the four pillars of Object Oriented Programming are in organizing code, reducing a program’s complexity, and overall increasing programming productivity.