Encapsulation is not just defining access methods and mutators for a class. This is a broader concept of object-oriented programming, consisting in minimizing the interdependence between classes, and it is usually implemented by hiding information.
The beauty of encapsulation is the power of changing things without affecting its users.
In an object-oriented programming language such as Java, you achieve encapsulation by hiding details using accessibility modifiers (public, protected, private, plus no modifier, which means closing the package). With these accessibility levels, you control the level of encapsulation, the less restrictive the more expensive change happens when it happens, and the more the class is associated with other dependent classes (for example, custom classes, subclasses).
Therefore, the goal is not to hide the data, but in the implementation details of how to manipulate this data.
The idea is to provide an open interface through which you access this data. You can subsequently change the internal representation of the data without compromising the public interface of the class. On the contrary, by exposing the data itself, you break encapsulation and, therefore, the ability to change the way data is managed without affecting its users. You are creating a dependency with the data itself, not with the public interface of the class. You will create the perfect cocktail for trouble when the โchangeโ finally finds you.
There are several reasons why you can encapsulate access to your fields. Joshua Bloch in his book "Effective Java" in paragraph 14: Minimize the availability of classes and members, mentions several good reasons that I quote here:
You can limit the values โโthat can be stored in the field (i.e. the floor must be F or M). You can take action when the field changes (trigger event, check, etc.). You can ensure thread safety by synchronizing the method. You can switch to a new view of the data (for example, computed fields, a different data type) However, encapsulation is more than hiding fields. In Java, you can hide entire classes, thereby hiding implementation details of the entire API. Think, for example, in the Arrays.asList () method. It returns a List implementation, but you don't care about which implementation, if it satisfies the List interface, right ?. The implementation may be changed in the future without affecting the users of the method.
The beauty of encapsulation
Now, in my opinion, to really understand encapsulation, you first need to understand abstraction.
Think, for example, about the level of abstraction in a car concept. The car is complex in its internal implementation. They have several subsystems, such as transmission system, fault system, fuel system, etc.
However, we have simplified its abstraction, and we interact with all cars in the world through the public interface of their abstraction. We know that all cars have a steering wheel through which we control the direction, they have a pedal, when you press it, you accelerate the car and control the speed, and the other when you press it, you stop it, and you have There is a mechanism that allows you to control if you are going forward or backward. These functions represent the public interface of the car abstraction. In the morning, you can drive a sedan, and then get out of it and drive an SUV during the day, as if it were the same.
However, few of us know the details of how all these functions are implemented under the hood. Think about the time when cars did not have a hydraulic steering system. One day, car manufacturers invented it, and they decide to get on it. However, this did not change the way users interact with them. At best, users experienced an improvement in using a directional system. Such a change was possible because the internal implementation of the car is encapsulated. Changes can be safely made without affecting the public interface.
Now think that car manufacturers have decided to put a fuel cap under the car, and not on one of its sides. You go and buy one of these new cars, and when you run out of gas, you go to the gas station and you wonโt find the fuel cap. Suddenly you realize that you are below the car, but you cannot reach it with the gas pump hose. Now we have violated the public interface agreement, and therefore the whole world is breaking, it is falling apart because things do not work as expected. Such a change would be worth millions. We will need to replace all gas pumps in the world. When we break encapsulation, we have to pay the price.
So, as you can see, the goal of encapsulation is to minimize interdependence and facilitate change. You maximize encapsulation by minimizing the impact of implementation details. The state of a class should be accessible only through its public interface.
I really recommend you read Alan Snyder's article, Encapsulation and Inheritance, in object-oriented programming languages. This link points to the original ACM paper, but I'm sure you can find the PDF copy through Google.