The 4 Pillars of OOP | BHM Edition
What is Object-oriented programming ?
Object-oriented programming (OOP) is a programming paradigm that organises software design around programmatically representing real world entities as objects.
*Note: Code is written in Python3
*Note: The words instance and object are used interchangeably
In honour of Black History Month, examples in this blog will celebrate the work of Black Tech Pioneers!
Classes, Objects and Methods
Classes and objects form an essential part of Object-oriented programming.
A class can be considered as a template/factory from which you can create an object. It describes the attributes and behaviours an object will have by grouping variables and methods respectively into a single unit.
- Class names are written in CamelCase
The SoftwarePioneer class specifies that a full name, profession and creation (amongst others) are necessary for defining a software pioneer, however it does not contain the full name, profession or creation of any specific software pioneer.
An object is a unique instance of a class. It can be can be defined as a data field that has it’s own unique attributes and behaviours. Custom objects are mutable by default and can be altered dynamically. Objects allow programmers to use the logic defined inside a class to complete a task.
- Variable names are written in snake_case
Mark E Dean can be thought of an an instance of the SoftwarePioneer class. His work at IBM led to the development of the first coloured PC monitor. The attribute values given such as “Computer Scientist and engineer” for profession and “Coloured Computer Monitor” for creation, etc are unique to him alone.
A method is a reusable set of statements that perform a task or calculate a value. It is defined within a class and as a result can only be called on an instance of that class.
Methods define the behaviours that an object can perform on its internal data and even on other objects within a program.
- Method names are written in snake_case
The method change_the_world returns a string stating a SoftwarePioneer instances full name, how they changed the world and in which year this occurred.
If we call this method on the instance mark, the following string is returned:
“Mark E Dean changed the world in 1980 with the creation of the Coloured Computer Monitor”
Abstraction is based on the assumption that users are only interested in interacting with the interface of a program and are typically unconcerned with its underlying implementation.
Thus the main idea of abstraction is to only show users the necessary details of your code by hiding the core implementation from them. This reduces complexity and results in a simpler interface.
The instance method recognition returns a string that states how long after a pioneers creation they were recognised for their work. Users of this method are interested in the string returned, however the underlying implementation on how the recognition calculation was made is not necessary for them to know and thus is hidden from the user.
When called on the instance marian, the following string is returned:
“ Marian Croak’s work was recognised in 2013 by The Women in Technology International hall of fame. This was approximately 18 years after their work pioneered Voice Over Internet Protocol (VoIP). ”
Inheritance allows programers to create new classes that use features defined in an existing class. This prevents programmers from repeating themselves by duplicating code.
A child class can make use of the variables and methods defined in the parent class it inherited from and can specify variables and methods that are unique to itself.
The HardwarePioneer class is a child class. It inherits the variables and methods defined in the SoftwarePioneer class.
As a result, calling the recognition method that was defined in the SoftwarePioneer class, on marie, an instance of the HardwarePioneer class, will return a string. Even though the recognition method was not explicitly defined in the HardwarePioneer class.
“Marie Van Brittan Brown’s work was recognised in 1969 by The National Scientists Committee. This was approximately 3 years after their work pioneered the Home Security System.“
Child classes can override or extend the attributes and methods of parent classes. Changes to the parent class are automatically passed on to child classes unless the attribute or method being changed has already been overridden in the child class.
The class attribute expertise was initially set to the value “Software” in the parent class. It has been overridden in the child class, so calling marie.expertise will return the string “Hardware”, whilst calling mark.expertise will return the string “Software”.
Due to inheritance, class hierarchies that act as a web of classes can be created. Where child classes that share the same parent class are referred to as sibling classes.
The basis of encapsulation is that programmers do not want external classes to directly alter an object’s attributes, particularly when working on large and complex programs. It helps programmers maintain control of access to data through information hiding.
Encapsulation refers to bundling data and methods that can operate on that data within a single unit, typically a class. This allows programmers to hide data within one class such that members of external classes can ONLY interact with the attributes of an object through getter (retrieving information) and setter (updating information) methods.
To make an attribute read only from outside the class it is defined in, a programmer would define a getter method but not a setter method. This way, the variable would only be referenced, not changed.
Encapsulation can be implemented by using access modifiers to restrict access to a class’s variables and methods.
3 main access modifiers are:
- Public: Public variables and methods can be accessed from anywhere in your program, both inside of the class hierarchy it is defined in as well as outside in the rest of the program
The change_the_world and recognition methods are examples of pubic methods, they can be accessed outside of the SoftwarePioneer class they are defined in.
- Private: Private variables and methods can ONLY be accessed from within the same class they are defined in. Attempting to call private variables and methods outside of the class they are defined in will return an AttributeError.
- Private variables and methods are prefixed with __ (double underscore).
__age_at_creation is a private variable, it can only be modified using the public setage() method, attempts to alter the __age_at_creation variable outside of this method will not update the variable.
To retrieve the value stored in the __age_at_creation variable for a specific instance, we must call the getage() method. Attempting to explicitly call __age_at_creation on the instance marie returns:
AttributeError: ‘HardwarePioneer’ object has no attribute ‘__age_at_creation’
- Protected: Protected variables and methods can be accessed within the class they are defined in and any child classes using getter and setter methods.
- Protected variables and methods are prefixed with _ (single underscore).
Polymorphism describes methods that are able to take on many forms such that different classes can implement the same method in different ways.
There are 2 forms of polymorphism: (1) Dynamic (2) Static
Dynamic polymorphism describes when a method signature exists in both a child class and a parent class and they share the same parameters but have different implementation. Thus methods can be written in the parent class with ought conditionals to account for which child class is being used.
For instances of the child class, it’s own implementation of the method will override the parent class’ implementation.
The form of the method signature that is called is determined dynamically as the program is run depending on which level in the class hierarchy it is invoked in.
The method change_the_world is defined in the SoftwarePioneer class and the child class HardwarePioneer. It prints different strings depending on the instance it is invoked on.
When called on lisa, an instance of the SoftwarePioneer class, the following string is returned:
“Lisa Gelobter changed the world in 1995 with the creation of Interactive multimedia, web animation (gifs) and video games”
When called on marie, an instance of the HardwarePioneer class, the following string is returned:
“Marie Van Brittan Brown changed the world in 1966, at the age of 44 with the creation of the Home Security System”
Static polymorphism is based the method overloading concept.
Multiple methods with the same name are defined in the SAME class with different parameters hence the method signatures differ. These differences can occur through the number of parameters declared, the order in which the parameters are declared in, or they accept parameters of different datatypes.
The different methods will have separate implementations but similar effects.
The form of the method signature that is called is determined when the program is compiled. The arguments given when the method is invoked will determine which method you want to invoke.
When using polymorphism and method overloading, programmers must ensure they are calling the correct form of the the methods so the program can function as intended.
Object-oriented programming helps programmers solve complex problems by grouping together related data and the operations you can perform on said data. Code is structured so that it’s functionality can be shared throughout the application with some restrictions created to control access to data.
Popular OOP languages include C++, Java, Python and Ruby.