30 Days Of Python 👨‍💻 - Day 9 - OOP Pillars

This article is a part of a 30 day Python challenge series. You can find the links to all the previous posts of this series here,
The first language that I was taught in school was BlueJ back when I was in fifth grade. It is a Java Development Environment designed for beginners and it was part of our school curriculum. That was my first introduction to Object-Oriented Programming. Although I didn’t understand much during those days, I still have vivid memories of our computer teacher explaining the pillars of OOP. I recollected some of our teacher’s analogies while exploring the principles of OOP in Python today and have tried to fuse them with some of my own.
 
There are basically 4 pillars or core principles of OOPs or so-called the pillars of OOP.
 

Encapsulation

 
While covering the basics of OOP in my previous post, I already covered about Encapsulation indirectly. Encapsulation in simple terms means to create a container where attributes and actions associated with those attributes are grouped together.
  1. class Avenger:  
  2.   def __init__(self, name, knownAs):  
  3.     self.name = name  
  4.     self.knownAs = knownAs  
  5.   
  6.   def reveal_identity(self):  
  7.     print(f'I am {self.name}, also known as {self.knownAs}')  
  8.   
  9. hulk = Avenger('Bruce Banner''Hulk')  
  10. iron_man = Avenger('Tony Stark''IronMan')  
  11.   
  12. hulk.reveal_identity() # I am Bruce Banner, also known as Hulk  
  13. iron_man.reveal_identity() # I am Tony Stark, also known as IronMan  
In the above class, the identity of each Avenger is revealed, when the reveal_identity method is called. In other words, their identity has been encapsulated. These methods which perform some action makes classes so powerful. While creating objects from the class, we can just call these methods to perform actions without bothering about how they do those actions. Just like Avengers!
 

Abstraction

 
To learn to drive a car, we need knowledge of just 3 things - A, B and C which is the accelerator, brake and clutch (Now with automatic cars, it even simpler). As drivers, we don’t need to know what makes the car accelerate or how the car comes to a halt when applying brakes. This is called abstraction. It is everywhere in real-life. A gentle press on a power button starts up a computer, a tap on the screen captures a photograph from our mobile etc. In the above example, the reveal_identity method is abstracted.
  1. class Avenger:  
  2.   def __init__(self, name, knownAs):  
  3.     self.name = name  
  4.     self.knownAs = knownAs  
  5.   
  6.   def reveal_identity(self):  
  7.     print(f'I am {self.name}, also known as {self.knownAs}')  
  8.   
  9. hulk = Avenger('Bruce Banner''Hulk')  
  10.   
  11. hulk.name = 'Thanos'  
  12. hulk.knownAs = 'Loki'  
  13.   
  14. hulk.reveal_identity() # I am Thanos, also known as Loki  
There is a problem with the class implementation above. Although a hulk was created, Loki came and decided to camouflage hulk into Thanos! This is not what I want so right now although there are encapsulation and abstraction implemented, the internal functionality can be tampered or modified from outside.
 
Python does not support the creation of private variables by default. Will have to explore more to see if it is possible to make variables and methods inaccessible and gain true abstraction.
 
There is a convention however to create a private variable by prefixing it with _. This allows other developers to recognize it as a private variable and not accidentally try to update those variables and methods( though they can). This is very similar to how we define a private variable in the JavaScript universe.
 

Inheritance

 
Inheritance as the name suggests means to inherit properties and functionalities from a parent. Based on a parent class, any number of sub-classes can be created that inherit from the parent class. This is done to share functionality among similar classes without writing the same logic again and again.
  1. class Player:  
  2.   def __init__(self, name, age):  
  3.     self.name = name  
  4.     self.age = age  
  5.   
  6.   def run(self):  
  7.     return f'{self.name} is running'  
  8.   
  9. class Cricketer(Player): # Syntax to inherit a class  
  10.   def catch_ball(self):  
  11.     return f'{self.name} Caught the ball'  
  12.   
  13. class Batsman(Cricketer):  
  14.   def swing_bat(self):  
  15.     return f'what a shot by {self.name}'  
  16.   
  17. player1 = Batsman('Virat Kohli'31)  
  18.   
  19. print(player1.run())  
  20. print(player1.catch_ball())  
  21. print(player1.swing_bat())  
player1 is an instance of Batsman class. Batsman is a sub-class of Cricketer. In the JavaScript world, the classes are inherited using the extends keyword. So I just created another comparison in my mental model between the two. Class Cricketer is again a subclass or child class of Player or in other words, it inherits Player class.
 
Since player1 is an object created from Batsman, it has the action to swing a bat.
 
It also inherits the ability to catch a ball from the Cricketer class. Very cool!
 
It also inherits the ability to run from the Player class.
 
In Python, there is a very handy built-in function, isinstance to check if an object is an instance of a class.
  1. class Player:  
  2.   def __init__(self, name, age):  
  3.     self.name = name  
  4.     self.age = age  
  5.   
  6.   def run(self):  
  7.     return f'{self.name} is running'  
  8.   
  9. class Cricketer(Player):  
  10.   def catch_ball(self):  
  11.     return f'{self.name} Caught the ball'  
  12.   
  13. class Batsman(Cricketer):  
  14.   def swing_bat(self):  
  15.     return f'what a shot by {self.name}'  
  16.   
  17. player1 = Batsman('Virat Kohli'31)  
  18.   
  19. print(isinstance(player1, Batsman)) # True  
  20. print(isinstance(player1, Cricketer)) # True  
  21. print(isinstance(player1, Player)) # True  
  22. print(isinstance(player1, object)) # True  
Since everything in Python is an object, all classes inherit all properties and methods from this base class object
 

Polymorphism

 
Poly means many and morphism means forms. So it literally means appearing in many forms. It is the feature by feature object classes can share the same methods, but those methods can do different actions based on what object is calling them.
  1. class ProgrammingLanguage:  
  2.   def __init__(self, name):  
  3.     self.name = name  
  4.   
  5. class JavaScript(ProgrammingLanguage):  
  6.   def comment(self):  
  7.     return(f'// A Comment in {self.name}')  
  8.   
  9. class Python(ProgrammingLanguage):  
  10.   def comment(self):  
  11.     return(f'# A comment in {self.name}')  
  12.   
  13. language1 = JavaScript('JavaScript')  
  14. language2 = Python('Python')  
  15.   
  16. def add_comment(languageObject):  
  17.   print(languageObject.comment())  
  18.   
  19. add_comment(language1) # // A Comment in JavaScript  
  20. add_comment(language2) # # A comment in Python  
  21.   
  22. for language in [language1, language2]:  
  23.   print(language.comment())  
  24. # // A Comment in JavaScript  
  25. # # A comment in Python  
In the above block of code, I created a generic function add_comment that accepts a programming language object and calls the comment() method on it. The same comment method, when called with different objects produced different result based on their implementation of the comment method.
 
In the second scenario, when looping through a list of language objects, it produced a different result when calling the same method on them.
 
This is polymorphism.
 
Although there are no specific guidelines or rules for when to use what OOP principle, it depends on the problem statement and the solution can be achieved in multiple ways applying the concepts of OOP.
 
That’s it for today. My mental model is perhaps gradually evolving, trying to build the latticework of programming concepts.
 
Tomorrow I have planned to finish off with the remaining OOP concepts and do some fun coding exercises before jumping into another exciting programming paradigm.
 
Have a nice one!


Similar Articles