The scope of this article is to help you understand the concepts of OOPS quickly. It is not an in-depth tutorial on coding with OOPS.
The Object-Oriented Programming system, also known as OOPS, is a hot topic for programming interviews.
If you’ve struggled to answer questions about OOPS, you’re not the only one. However, OOPS has many advantages and can be fun to learn, especially in your favorite programming language. This shot aims to help you improve your skills and knowledge.
Let’s get started with OOPS.
There are four pillars:
Let’s have a look at each of them.
Encapsulation: To enclose something in or as if in a capsule.
If you understand the meaning, you can use this concept with your code. Let’s look at the example.
class Cat:def __init__(self):self.sound = "meow"def speak(self):print("Cat says: {}".format(self.sound))c = Cat()c.speak()# change the pricec.sound = "bow-wow"c.speak()
In the example above, the Cat
class has a variable sound set to the default value in the constructor. Later on, we also change the value of this variable, i.e., c.sound = "bow-wow"
.
Now that you know the meaning of encapsulation as per the definition above, consider class as a capsule. Do you think this code follows encapsulation?
It does not. To avoid this, we can declare the private variables. In Python, we denote private attributes using an underscore as the prefix, i.e., single _
or double __
.
class Cat:def __init__(self):self.__sound = "meow"def speak(self):print("Cat says: {}".format(self.__sound))c = Cat()c.speak()# change the pricec.sound = "bow-wow"c.speak()
Now, it has been encapsulated.
Here are some practical examples of encapsulation:
A bank application does not allow a client to change an account’s balance.
This is also used to hide the data. Let’s say you log into your email account. There are a lot of processes in the backend that you have no control over. Your password will most likely be retrieved in an encrypted form, verified, and only then will you be given access. You do not have any control over how the password is
Inherit: To receive a quality, characteristic, etc., from your parents or family.
As you see the definition above, inheritance allows us to define a class that inherits methods and properties from another class. Let’s say you need a new class with little or no modification, and you then apply this concept.
The base class is called the parent class, and the derived class is known as a child.
Let’s look at an example.
class Family:def __init__(self, family_name, number_of_members, country):self.family_name = family_nameself.number_of_members = number_of_membersself.country=countrydef member_says(self):print(f"Hey, I am from {self.family_name} family and there are {self.number_of_members} members in family")class Family_detailed:def __init__(self, family_name, number_of_members, country):self.family_name = family_nameself.number_of_members = number_of_membersself.country=countrydef member_says(self):print(f"Hey, I am from {self.family_name} family and there are {self.number_of_members} members in family")def which_country(self):print(f"The {self.family_name} family has roots from {self.country}" )a = Family("Rodrigues",5,"Peru")b = Family_detailed("Bezos",15,"United States of America")a.member_says()b.member_says()b.which_country()
The purpose of the first class is to display family names and the number of members, but the second class wants to display the same information along with the country. As you can see, there is a lot of common code here; let’s use inheritance to make it simpler.
class Family:def __init__(self, family_name, number_of_members, country):self.family_name = family_nameself.number_of_members = number_of_membersself.country=countrydef member_says(self):print(f"Hey, I am from {self.family_name} family and there are {self.number_of_members} members in family")class Family_detailed(Family):def which_country(self):print(f"The {self.family_name} family has roots from {self.country}" )a = Family("Rodrigues",5,"Peru")b = Family_detailed("Bezos",15,"United States of America")a.member_says()b.member_says()b.which_country()
As you can see, inheritance reduces the code significantly.
Abstraction: A general idea rather than one that relates to a particular object, person, or situation.
To understand this pillar better, let’s use the example of a car. People do not see a car as thousands of individual parts. Instead, they see it as a well-defined object with unique behavior. They do not need to understand the complexity of those parts and how they collaborate.
In simple terms, abstraction hides the internal implementations of a process or method from the user. In this way, the user knows what they do but not how it is done.
Abstraction is a bit different from the other pillars. Python does not grant abstract classes by default. Instead, Python comes with a module that fits the base for Abstract Base classes (ABC). A method becomes abstract when decorated with the keyword @abstractmethod
.
Let’s use a simple example.
from abc import ABC, abstractmethodclass Company(ABC):def work(self):passclass Manager(Company):def work(self):print("I assign work to and manage team")class Employee(Company):def work(self):print("I complete the work assigned to me")# Driver codeR = Manager()R.work()K = Employee()K.work()
Polymorphism: The condition of occurrence in several different forms.
To understand the polymorphism pillar, let’s use the cartoon character Ben 10 as an example. He is one person, but he serves the world in multiple forms.
So, in programming terms, polymorphism refers to the use of a single method/operator to represent different types in different scenarios.
Python can use multiple classes in the same way, through polymorphism. To serve this purpose, we can create a loop that iterates through a tuple of objects. This will allow us to call methods without looking at the class to which the object points.
class Class1():def pt(self):print("This function determines class 1")class Class2():def pt(self):print("This function determines class 2.")obj1 = Class1()obj2 = Class2()for type in (obj1, obj2): # creating a loop to iterate through the obj1, obj2type.pt()
This works similarly for operators. Let’s look at the +
operator.
> print(1+2) 3 > print ("a"+"b") > ab
As you see, the +
operator behaves in a different way with different datatypes.
Free Resources