Encapsulation With Example And Benefits In Java & OOP

Encapsulation With Example And Benefits In Java & OOP

Object-oriented programming tries to model real-life objects into the programming world. This makes the programs easy to co-relate with real-world and understand. Encapsulation is one of the key concepts which plays crucial role in this modelling, along with Abstraction and Polymorphism.

For impatient readers, I will just define the encapsulation and then move on with the example.

  1. To encase in or as if in a capsule
  2. To express in a brief summary
Technical translation of encapsulation,
  1. Wrapping of data in a construct such that it hides its internal data
  2. Provide behaviour methods to control access of data in desired fashion

Analysing Real-life Objects

What we expect from real-life objects is behaviour. Take a car as an example. What are expectations from Car? Start the car. Accelerate the car. Accelerate more n more. Break. Move to reverse slowly. Stop. That’s it. To achieve these behaviour, you are provided with some of the mechanisms. Ignition to start and stop the car. Gearbox, accelerator and break to increase or decrease the speed of car. You use these accelerator and break to achieve the desired speed of the car.

How this relates with Encapsulation? To see that, lets create a vanilla version of the Car class in Java.

Warning: Create this class in your application at your own risk.

class Car{
public float speed =0;
public boolean isReverse = false;
public boolean isStarted = false;
}

You believe that all your clients of Car class are sensible and will use it as below.

class Main{
public static void main(args String[]){
Car car = new Car();
car.isStarted = true;
car.setSpeed = 10;
car.setSpeed = 20;
car.setSpeed = 30;
car.setSpeed = 20;
car.setSpeed = 10;
car.setSpeed = 0;
car.isReverse = true;
car.setSpeed = 10;
car.setSpeed = 0;
car.isStarted = false;
}

How client code may will use it.

class Main{
public static void main(args String[]){
Car car = new Car();
// No need to start??
car.speed = 100; // Turbo mode directly to 100
car.speed = 0; // Turbo break
}
class Main{
public static void main(args String[]){
Car car = new Car();
car.isStarted = true;
car.isReverse = true;
car.setSpeed = 100;
}

You see what is wrong here. Access to data of the Car is uncontrolled. Real-life objects always impose constraints on the way object can be used. What can we do to make this Car class usable?

  1. Hide internal data(speed, isStarted, isReverse) from client
  2. Provide behaviour methods to provide controlled access to its data.

Encapsulation In Java

Java provides 4 different access modifiers to control visibility of internal data from outside world. private, protected, default(no access modifier) and public. In this article, I will not go in details of these each modifier but here is the quick reference for each of them.

private – Most restrictive, allows only class level access.
default – Package level access.
protected – Package level access + access to sub-classes.
public – Least restrictive, doesn’t impose any visibility constraint.

Let us see encapsulation of the car class to achieve desired behaviour.

class Car{

private float speed =0;
private boolean isReverse = false;
private boolean isStarted = false;

public void start(){
if(isStarted()){
// the car is already started
}else{
isStarted = true;
}
}

public void accelerate(){
if(isStarted){
speed += 10;
}else{
// car is not started yet
}
}

public void doBreak(){
if(isStarted){
speed -= 10;
}else{
// car is not started yet
}
}

public void stop(){
if(isStarted){
isStarted = false;
}else{
// car is already stopped
}
}

}

Client of this Car class will look like below.

class Main{
public static void main(args String[]){
Car car = new Car();
car.reverse(); // Display error or throw exception
car.start();
car.accelerate();
car.accelerate();
car.accelerate();
car.doBreak();
car.doBreak();
car.doBreak();
car.stop();
}

Calling accelerate() and doBreak() methods several times may look undesired, but this is just to explain the concept. You can add any fancy behaviour inside the methods to provide more acceleration or something like turbo break.

Another example of the encapsulation is BankAccount. Clients cannot directly access balance of the account. The access is controlled via methods like checkBalance(), deposit(), withdraw().

Benefits of Encapsulation

  1. Makes it easy to model real-world entities – hence easy to understand and maintain
  2. Control the way data is accessed or modified
  3. Makes the class easy to use for clients
  4. Increase reusability
  5. Aids to the flexibility of design e.g. It is possible to add accelerationConfiguration field in the Car. This will enable you to have different acceleration behaviour of each car.

Summary

Encapsulation wraps the data to hide it and binds behaviour with it to have controlled access to data. Encapsulation makes it easy to see your object as real-life entities which makes the class easy to understand, maintain, reuse and makes the design flexible.

6 Comments

  1. Manish Kumar 2 years ago

    Hi, I have a doubt on points given about benefits of encapsulation, Now my question is .
    how can you justify, “encapsulation increase flexibility and increase re-usability” please justify each one , and thanks for your contribution to understand encapsulation and you have delivered such a nice example!.

    • Author
      Vishal Shukla 2 years ago

      Hi Manoj,

      Thanks for your warm feedback about the post.

      I would put it this way,

      Reusability:

      No encapsulation == No behaviour to objects
      No behaviours == conventional logic methods in outer layers

      A, B, C layers use component X with behaviour, then behaviour is at single place.
      A, B, C layers use component X without behaviour, they will their own, duplicated implemntations.

      Flexibility:

      Its all about low level – intelligent – components. Each one knowing just about themselves and very little about others, making them losely coupled. If you take the encapsulation out of the equation, you just can’t give intelligence to these low level components – as they would turn out to be dumb data objects. Hence pushing the intelligence to upper most level – a monolithic procedural-style method containing all the logic.

      I hope the explanation makes sense.

      Best Regards,
      Vishal Shukla

  2. Pinal Shah 2 years ago

    Hi .. I really love your article…its amazing…now i want your permission to use some of your content in my book..i am planning to write a book on Java …again thank you..really a good post…Thank You

    • Author
      Vishal Shukla 2 years ago

      Hi Pinal,

      Glad to know that you liked the content. Feel free to use it in your book along with the citation of the source.

      Best Regards,
      Vishal Shukla

  3. santosh 2 years ago

    Hi Vishal,
    Thank you very much for elucidating this concept. I found it very much helpful.

  4. haribabu saladi 1 year ago

    Hi vishal,

    This is very nice article.. but still i have one doubt.. we can access the private variables data via public setters and getter mothods right.. then how can we achieve control from client or outside world?

    Thanks
    Hari saladi

Leave a reply

Your email address will not be published. Required fields are marked *

*