Analysing Real-life Objects
Object-oriented programming tries to model real-life objects into the programming world. This makes the programs easy to co-relate with the real-world and understand. Encapsulation is one of the key concepts which plays a crucial role in this modeling along with Abstraction and Polymorphism.
Encapsulation In Java
First, what do we expect from real-life objects is behavior. Take a car as an example. What are the expectations from a car? Start the car, accelerate, brake, move in reverse slowly, and stop. To achieve these behaviors, you are provided with certain mechanisms: ignition to start and stop, gearbox, accelerator, and brake to increase or decrease speed. You use these controls to achieve the desired speed.
How This Relates to Encapsulation
Let's understand this with a basic version of a Car class in Java. Access to data should be controlled. However, real-life objects often impose constraints on how objects can be used.
In the real world, you get an accelerator to speed up the car and a brake to reduce speed. Shouldn't our objects reflect this fact as well? Java provides 4 different access modifiers to control visibility of internal data:
- private – Most restrictive, allows only class-level access
- default (no access modifier) – Package level access
- protected – Package level access + access to sub-classes
- public – Least restrictive, no visibility constraints
By encapsulating the Car class with proper access modifiers, client code becomes more realistic. Instead of directly accessing car properties, clients use controlled methods like accelerate(), brake(), and stop().
Benefits of Encapsulation
Reusability
Without encapsulation, there is no behavior to objects. Without behaviors, you resort to conventional logic methods in outer layers. When multiple layers use a component with behavior, that behavior is at a single place. When a component lacks behavior, each layer will have its own duplicated implementations.
Flexibility
Encapsulation creates low-level, intelligent components. Each component knows about itself and very little about others, making them loosely coupled. Without encapsulation, you cannot give intelligence to low-level components, turning them into dumb data objects and pushing all intelligence to the highest level, resulting in monolithic, procedural-style code.
Additional Benefits
Encapsulation wraps the data to hide internals from the outside world. On top of that, it binds behaviors with objects to provide controlled access to the data. This makes it easy to see your object as a real-life entity, making the class easy to understand, maintain, and reuse for different purposes.
Another example is BankAccount, where clients cannot directly access the balance. Access to the balance is controlled via methods like checkBalance(), deposit(), and withdraw().