Understanding Encapsulation, Inheritance, Polymorphism, Abstraction in OOPs
As the name suggests, Object-Oriented Programming or OOPs refers to languages that use objects in programming. Object-oriented programming aims to implement real-world entities like inheritance, hiding, polymorphism etc in programming. The main aim of OOP is to bind together the data and the functions that operate on them so that no other part of the code can access this data except that function. In this article, we will understand all the concepts of OOP’s along with an example.
Let’s assume that we have a bird class and we are creating a list of birds. Let’s understand the OOP’s concepts used in this bird creation.
Inheritance: For any bird, there are a set of predefined properties which are common for all the birds and there are a set of properties which are specific for a particular bird. Therefore, intuitively, we can say that all the birds inherit the common features like wings, legs, eyes, etc. Therefore, in the object-oriented way of representing the birds, we first declare a bird class with a set of properties which are common to all the birds. By doing this, we can avoid declaring these common properties in every bird which we create. Instead, we can simply inherit the bird class in all the birds which we create. The following is an example of how the concept of inheritance is implemented.
After the bird class is implemented, if we wish to create a pigeon, then we simply inherit the above Bird class.
Encapsulation: Now, we have defined the properties of the bird class and the attributes which the birds have like colour, wings, legs can be initialized by creating an object of the bird class. However, if we simply are able to change the properties of the bird class just by the reference of the object, then the attributes lose the information by which it was initially initialized.
For example, let’s say we have initially created a pigeon with a grey colour by creating a constructor, any user with the instance of the object of the pigeon can change this colour to red or black by simply referring the attribute with “this” keyword. Therefore, in order to avoid this, we enclose the properties in the methods. These methods are called the getters and setters of the attributes. The idea is to simply enclose the initialization and retrieval of the attributes in a method instead of directly referring the attribute directly. This also gives an advantage because the setters give us complete control in setting the value to the attribute and help us to restrict the unnecessary changes. For example, if a pigeon is created(born) with a grey colour, it doesn’t change until the pigeon dies. So, a user who is using simply shouldn’t be able to change the colour as per his wish. The following is the implementation of the getters and setters for the above Bird class.
Polymorphism: The word polymorphism is made of two words poly and morph, where poly means many and morphs means forms. In programming, polymorphism is a feature that allows one interface to be used for a general class of actions. In the above concept of a bird and pigeon, a pigeon is inherently a bird. And also, if the birds are further categorized into multiple categories like flying birds, flightless birds, etc. the pigeon also fits into the flying bird’s category. And also, if the animal class is further categorized into plant-eating animals and meat-eating animals, the pigeon again comes into the plant-eating animal’s category. Therefore, the idea of polymorphism is the ability of the same object to take multiple forms. There are two types of polymorphism:
- Compile Time Polymorphism: It is also known as static polymorphism. This type of polymorphism is achieved by function overloading or operator overloading. It occurs when we define multiple methods with different signatures and the compiler knows which method needs to be executed based on the method signatures.
- Run Time Polymorphism: It is also known as Dynamic Method Dispatch. It is a process in which a function call to the overridden method is resolved at Runtime. This type of polymorphism is achieved by Method Overriding. When the same method with the same parameters is overridden with different contexts, the compiler doesn’t have any idea that the method is overridden. It simply checks if the method exists and during the runtime, it executes the functions which have been overridden.
In java, we can also upcast and downcast the objects. The core idea behind this concept is also polymorphism. The idea is that the object of the bird can have the value of the pigeon because it inheriting the features of the bird. Therefore, a parent object can also be initialized with the child properties if both the objects extend each other in the following way:
Bird b = new Pigeon();
Abstraction: Abstraction in general means hiding. In the above scenario of the bird and pigeon, let’s say there is a user who wants to see pigeon fly. The user is simply interested in seeing the pigeon fly but not interested in how the bird is actually flying. Therefore, in the above scenario where the user wishes to make it fly, he will simply call the fly method by using pigeon.fly() where the pigeon is the object of the bird pigeon. Therefore, abstraction means the art of representing the essential features without concerning about the background details. In Java, the abstraction is implemented through the use of interface and abstract classes. We can achieve complete abstraction with the use of Interface whereas a partial or a complete abstraction can be achieved with the use of abstract classes. The reason why abstraction is considered as one of the important concepts is:
- It reduces the complexity of viewing things.
- Avoids code duplication and increases reusability.
- Helps to increase security of an application or program as only important details are provided to the user.