In object-oriented programming languages, encapsulation is used to refer to one of two related but distinct notions, and sometimes to the combination thereof:
- A language mechanism for restricting direct access to some of the object's components.
- A language construct that facilitates the bundling of data with the methods (or other functions) operating on that data
This is how Wikipedia defines Encapsulation. It is a very bulky and complex definition of Encapsulation but don't worry, over the course of this lesson we will slowly unroll it so that by the end of the lesson we have a good grasp on this concept. For the purposes of our discussion, we will look at both properties which are defined under Encapsulation. First one being restricting direct access to some of the object's components. Rephrasing it in a little simpler wording, it means hiding some of the implementation details from the outside world. This is also known as Data hiding. The second point in the definition above on facilitating bundling of data with methods means characteristics and behaviour are combined into a single unit.
Let's look at an ATM. You go to the ATM, swipe your card, enter your pin and then enter the amount of money you want to withdraw. ATM processes your request and gives you the money. If you were to see ATM through object-oriented lens you will realize that ATM contains different denominations of currency notes and all the operations to read your debit card, verify your pin, count currency notes, dispense the money to you, etc. ATM combines all the different denominations of currency notes and all the operations required to withdraw money into a single unit. You interact with this one machine which is wrapping all this together and very conveniently withdraw cash. Here ATM can be viewed as a class which is wrapping together the data which are the currency notes and methods which are the operations required to withdraw money into a single unit. In other words, we can say that ATM encapsulates money and operations required to withdraw it into a single unit.
You can interact with the ATM only through the numeric keypad and the onscreen options it provides. You cannot access the details about internal data like how much money does this ATM has, how many notes of each denomination are present, how much money has been withdrawn so far, etc. This is the Data Hiding concept of Encapsulation.
Encapsulation & Abstraction are complementary
You might be a little confused at this point between Abstraction and Encapsulation as I said something similar for Abstraction too that it hides the background details. In fact, Abstraction and Encapsulation are complementary concepts. Abstraction solves the problem at the design level whereas Encapsulation solves the problem at implementation level. Abstraction cares about what something does but not how it does it. Encapsulation cares about how something does what is does such that others don't have to worry about the implementation details. Going back to our ATM example, when I am designing the ATM, I will think about what steps the user needs to follow in order to withdraw money. I will list down that the user will swipe his card, enter pin, enter amount and finally collect cash, that's Abstraction at work. I am only focusing on things that are relevant from the user's point of view and eliminating all other stuff. When I am actually making that ATM, I will look at the design and go through the steps and think about how I should build this ATM so that the user can withdraw cash by just following these steps and not worrying about anything else, that's Encapsulation. Hence, we can say that Encapsulation is a way to implement Data Abstraction. Encapsulation hides the details of the implementation of an object.
Java supports Encapsulation through classes and access specifiers - public, private and protected. We will look into this a little bit later in this course.