Understanding OOP.
OOP is one of most fundamental software engineering paradigm that every Software Engineer must grasp when entering the Software Engineering world as a Java Programmer. Let it be any OOP based language: Python, C#; we must have our OOP principles set straight. OOP works on the basis of classes and objects: where a class is a defined template and objects are instantiated to create a template of the class.
“Understanding these principles will help you write leaner, cleaner and re-usable code helping you to maintain your codebase and make changes easily without breaking the rest of your code.” — This concept is also known as de-coupling. This is where you code is not inter-dependent.
Lets dive into the code and let us walkthrough these OOP principles. For demonstration purposes, I will be using Java as my programming language. But these principles are the same for any OOP Based Language. So try along in your preferred OOP Language.
1. Encapsulation
Encapsulation is a concept where the data members (variables) in the class is wrapped by the class in a way that it is directly accessible on within the class and no other class can directly access the data members. In-order to achieve this, we make the data members private
and use accessors
and modifiers
to access the data members from outside of the class.
This is illustrated below.
In the figure above, we can see a Class — Cat
. This class has private data members ensuring that no class can directly access the data members of this class. This access is only provided via the setter
methods for each attribute. And if you observe closely, you can see that one variable animalFamily
is marked as readonly
. This was achieved by initializing the variable in the constructor and then providing only getter
for it.
2. Abstraction
Abstraction is similar to encapsulation, but it is not the same. Abstraction is a principle where certain implementation details are hidden from the client and only the required details are exposed to the client.
In OOP, when a class is declared abstract, it cannot be instantiated, because it has no “real world” application to it. Therefore, these classes must follow another principle: Inheritance, to provide a real world application to it.
Abstraction can be achieved as follows:
The figure above illustrates an Abstract class. The class Animal has no real world implementation. These allow us to hide certain data from the client and expose only the required data.
In the next concept, we will look at how to utilize this abstract class.
3. Inheritance
Inheritance. This is also known as the parent-child relationship. The child extends the parent and retrieves all the non-private attributes and the methods of the parent class.
So, why is inheritance used? Lets assume we have a set of classes that have the same attributes. For example: Cat, Dog, Sheep all share some common attributes: age, gender, origin, name. If we were to map these in individual classes, we would have to create 3 separate classes. But this is not efficient. Therefore, we can add all the common attributes to the parent class — Animal
and have the other classes extend the Animal class allowing them to get the required data members without code replication.
So how does this actually look?
In the figure above, the abstract class — Animal is being utilized. We can see that a class — Cat
has been created the “extends” the Animal class. This indicates that the Cat is an Animal. Since we are extending an Abstract class, we must override any abstract methods that we have declared. This allows us to abstract implementation details from the user and provide custom implementations for the same method. This is where the “makeSound()” method has been overridden and has been given a custom implementation unique for the cat.
How does it work? Its simple. We create an object of Child while referencing it to the Parent Class.
eg: Animal theCat = new Cat();
This allows the theCat
object to obtain the overridden implementations.
That is, in a nutshell, the way in which inheritance works.
4. Polymorphism
We have reached the final principle. This is said to be Polymorphism.
What is Polymorphism?
It is the way in which anything can have alternate forms. So, how do we achieve this in code?
There are two ways that we can achieve polymorphism.
- Method Overloading
- Method Overriding
Method Overloading
Method overloading is a concept where in-a-class, a method with the same name and same return type is provided with different implementations and different input parameters.
Eg:
This is an example of overloading. This shows that there are three add
methods declared. All these methods have different input parameters and different number of input parameters as well. For overloading, the methods must be declared in the same class
This helps in maintaining more cleaner and understandable code.
Method Overriding
If you remember closely during inheritance, I talked about “overriding” the method declared in the parent class when extending the child class. Overriding means: providing a new implementation to a method in a different class. This means that overriding is used only in parent-child relationships.
Viola!.
If you reached the end of this article, you have successfully understood the fundamental principles of OOP. I hope this article was of a use to everyone that read it.
Thank you for taking your time to read this.
Till then,
Happy Coding.