“I hope the field of computer science never loses its sense of fun. ... What you know about computing other people will learn. Don’t feel as if the key to successful computing is only in your hands. What’s in your hands I think and hope is intelligence: the ability to see the machine as more than when you were ﬁrst led up to it, that you can make it more.”
― Alan J. Perlis, Structure and Interpretation of Computer Programs
To meet the demands of the Covid-19 era, many businesses are undergoing a digital transformation. Thus, acquiring or strengthening your programming skills will be essential for your future career. Specifically, object-oriented programming is a dominant programming paradigm that you will encounter at some point in your programming career. In this article, I will explain the four primary principles of object-oriented programming that you'll need to know to thrive on your programming journey. In addition, I will take you through some examples where I will explain the concepts using the Python Programming Language. But first, let's start by first exploring the definition of object-oriented programming.
“An object-oriented program is a set of interacting objects, each one responsible for its own activities and data.” – (Robertson, 2006)
In essence, an object-oriented program (OOP) is deeply rooted in the concept of objects, where each object contains a unique set of attributes/characteristics (properties), and executes a set of operations (methods). A class is a blueprint of an object and classes share a series of common features. For example, using Python we define a class called Employee.
class Employee: # initializer def __init__(self, name, age, employee_id, department, title): self.name = name self.age = age self.employee_id = employee_id self.department = department self.title = title #method def details(self): print("Employee Name:", self.name) print("Employee Age:" , self.age) print("Employee ID:", self.employee_id) print("Employee Department:" , self.department) print("Employment title:" , self.title) #instance of class emp1 = Employee("Luke", 40, "4001", "Operations Management", "Business Analyst") #calling the instance method emp1.details()
#Output Employee Name: Luke Employee Age: 40 Employee ID: 4001 Employee Department: Operations Management Employment title: Business Analyst
The self parameter is used as a reference to the individual object itself. Note that the self parameter is used to set or get the attributes of a particular instance. Our employee class also has attributes, which are unique characteristics that differentiate an object from another (name, age, id, department, and title). The method is defined in details and an instance of the employee class is shown in emp1.
Now that you have seen an example of OOP in action let's explore its four core principles.
In OOP, encapsulation involves the bundling of data and methods into one unit and hiding it from the external world. In such a way that each object can be regarded as a “black box” and its internal state or operations are hidden from all other objects. (Robertson, 2006). The encapsulation process is more formally known as information hiding, whereby one class does not have direct access to the data in other classes, or access is managed using instance methods. In this way, encapsulation provides an added layer of security in your code and prevents data breaches from outside sources. Let's now explore a real-world example of encapsulation — an aeroplane. The external features include the wings, wheels, windows, empennage, and fuselage. However, the power plant (i.e., the aircraft engine) is hidden from the external world and protected using a cover. So how can you “hide” the attributes of a class in python? It's simple, you can use the private access modifier to ensure that the members of a class are accessible only within a specific class using a double underscore ‘__’ before the data member of that class.
Let's now explore inheritance in OOP.
This is one of my favourite principles in OOP. With inheritance, a child class will inherit all the methods and properties of the parent class or base class. Let's add a child class called Supervisor to our Employee class. This code is largely inspired by this example.
# parent class class Employee: # initializer def __init__(self, name, age, employee_id, department, title): self.name = name self.age = age self.employee_id = employee_id self.department = department self.title = title #method def details(self): print("Employee Name:", self.name) print("Employee Age:" , self.age) print("Employee ID:", self.employee_id) print("Employee Department:" , self.department) print("Employment title:" , self.title) # child class class Supervisor(Employee): def __init__(self, name, age, employee_id, department, title, project_name): super().__init__(name, age, employee_id, department, title) print("Welcome to our E-Gov Team!__init__()") self.project = project_name def projectDetail(self): print("Project: %s" %self.project) # object of Supervisor class obj = Supervisor("Roxanne", 37, "2340", "IT", "Scrum Master", "E-Gov") # output print("-----Supervisor Detail-----") obj.details() print("-----Project Detail-----") obj.projectDetail()
#Output Welcome to our E-Gov Team!__init__() -----Supervisor Detail----- Employee Name: Roxanne Employee Age: 37 Employee ID: 2340 Employee Department: IT Employment title: Scrum Master -----Project Detail----- Project: E-Gov
So here's the explanation – We already established (see comments #) that class Employee is the parent class and Supervisor is the child class. Explore the code and you'll see that the Supervisor class inherits attributes and methods from the Employee class. Did you spot the difference between the parent and child class? Look again. The Supervisor class also incorporates the
__init__ method but it takes an additional argument i.e.,
name, age, employee_id, department, title, project_name when compared to its parent class which takes the following arguments
name, age, employee_id, department, title.
N.B. - the super() method in python allows us to access the
__init__ method of the base/parent class.
Polymorphism in literal terms means having many forms. i.e., Poly – Many and Morphism – many forms. In OOP, polymorphism can occur using inbuilt functions as well as using class methods. Here is an example using the inbuilt method (+ operator)
#performs the addition arthmetic operation int1 = 5 int2 = 10 print(int1 + int2)
In another example, the (+ operator) is leveraged to perform string concatenation.
#performs a string concatenation a = "Girls too " b = "can code!" c = a + b print(c)
#Output Girls too can code!
Below is an example of polymorphism using class types.
class Jamaica(): def counties(self): print("Jamaica is divided into three counties – Cornwall, Middlesex and Surrey.") def climate(self): print("Jamaica has a tropical climate.") def type(self): print("Jamaica is a developing country.") class USA(): def counties(self): print("The USA has 3,006 counties.") def climate(self): print("USA has a continental climate.") def type(self): print("US is a developed country.") obj_jam = Jamaica() obj_usa = USA() for country in (obj_jam, obj_usa): country.counties() country.climate() country.type()
Jamaica is divided into three counties – Cornwall, Middlesex and Surrey. Jamaica has a tropical climate. Jamaica is a developing country. The USA has 3,006 counties. USA has a continental climate. US is a developed country.
Let's now talk about Abstraction in OOP.
According to Ask Python Abstraction is defined as follows. A feature in OOP whereby a user remains unaware of the basic implementation of a function property. So the user is able to view the basic functionalities and internal details are hidden. For example, whenever we place our food in the microwave, we press the timer and when the process is completed we get hot food. However, we do not see with the naked eye the internal details of how the microwave heats our food.
In OOP, there are two types of abstraction. Data Abstraction, whereby object data is hidden from the outside world. However, if needed, access to the object's data is provided through particular methods. Process abstraction, whereby not all the details about all the object's functionalities are provided. So “when we hide the internal implementation of the different functions involved in a user operation, it creates process abstraction.”
By hiding the irrelevant details of a programme, we can reduce complexity and increase efficiency.
N.B. By default, Python doesn’t provide abstract classes. In essence, it is equipped with the in-built Abstract Base classes (ABC) module, which provides the infrastructure for defining abstract base classes. Please refer to https://docs.python.org/3/library/abc.html for more details on how (ABCs) work.
# Python program demonstrating how the abstract base class works from abc import ABC, abstractmethod class Vehicle(ABC): @abstractmethod def noofdoors(self): pass class Sedan(Vehicle): # overriding abstract method def noofdoors(self): print("I am a Sedan and I have 4 doors.") class HatchBack(Vehicle): # overriding abstract method def noofdoors(self): print("I am a Hatchback and I have 5 doors.") class SportsCar(Vehicle): # overriding abstract method def noofdoors(self): print("I am a Sports Car and I have 2 doors.") A = Sedan() A.noofdoors() B = HatchBack() B.noofdoors() C= SportsCar() C.noofdoors()
Output I am a Sedan and I have 4 doors. I am a Hatchback and I have 5 doors. I am a Sports Car and I have 2 doors.
For more information on OOP, you may explore any of the following languages.
I hope you found this information useful. Please feel free to share your comments using the comment emoticon.
Robertson, L. A. (2006). Simple Program Design, A Step-by-Step Approach. Nelson Education.