Understanding Encapsulation in Java

Encapsulation is an object oriented programming (OOP) implementation technique where we are related data members in a single unit (class) and define member functions to allow indirect and restricted control from the user side. This results in clean and well managed code with increased security. Encapsulation is the most important concept of object oriented programming.

In this article, you will understand:

  • What is encapsulation? with a real life example + code example
  • What is data abstraction? with a code example
  • Problem one can face of encapsulation is not used

Before we go into encapsulation, we will revisit some of the basic Object Oriented programming (OOP) concepts. Object oriented programming consists of two main things: Objects and classes.

Objects are an identifiable entity with some characterstics and behaviour or a class in execution with actual data.

Classes are a group of objects that share common properties and relationships or a structure for similar objects with data members and member functions defined.

Encapsulation is the way of combining both data and the function that operate on that data under a single unit.

Definition:

The wrapping up of data and functions(that operate on the data) into a single unit (called class) is known as encapsulation

The only way to access the data is provided by the function (that are combined along with the data). These functions are called member functions or methods in Java. The data cannot be accessed directly.If you want to read a dataitem in an object(an instance of class), you call a member function in the object.It will read the item and return the value to you.You can't access the data directly.The data is hidden, so it is safe from accidental alteration.Data and its functions are said to be encapsulated into a single entity.

What is a Real life example of encapsulation?

Let us now consider an analogy to encapsulation:

In a big company there are so many departments: Sales, Accounts, Payroll, Purchase, Production, etc.

Each department has its own personnel to maintain its data. Suppose an employee in the production department wants to know how much raw material has been purchased for the next month. The production department employee would not be allowed to himself go through the purchase department data files. Rather he will have to issue a memo to the 'purchase' requesting for the required information. Then some employee of the purchase department will go through the purchase data files and send the reply with the asked information.

This practice ensures that the data is accessed accurately and that it is safe from outsiders. Therefore we can say that the department data and the department employees are encapsulated into a single entity, the department.

Encapsulation is a way to implement data abstraction.Data abstraction focuses on the observable behaviour of an object whereas encapsulation focuses upon the implementation that gives rise to this behaviour.

Code example of encapsulation

Here is an example of encapsulation

class EncapsulationDemo
{
    private int rollNo;
    private String studentName;
    private int studentAge;
    //Getter and Setter methods
    public int getrollNo()
    {
        return rollNo;
    }
    public String getStudentName()
    {
        return studentName;
    }
    public int getStudentAge()
    {
        return studentAge;
    }
    public void setStudentAge(int newValue)
    {
        studentAge = newValue;
    }
    public void setStudentName(String newValue)
    {
        studentName = newValue;
    }
    public void setRollNo(int newValue)
    {
        rollNo = newValue;
    }
}
public class EncapsTest
{
    public static void main(String args[])
    {
         EncapsulationDemo obj = new EncapsulationDemo();
         obj.setStudentName("Ram");
         obj.setStudentAge(16);
         obj.setRollNo(24);
         System.out.println("Student Name: " + obj.getStudentName());
         System.out.println("Student Rollno: " + obj.getRollNo());
         System.out.println("Student Age: " + obj.getStudentAge());
    } 
}

Output

Student Name: Ram
Student Rollno:24
Student Age: 16

It simply means exposing only the essential features of an entity and hiding the features that are unnecessary.It only indicates important things to the user and hides the internal details, ie. While sending SMS, you just type the text and send the message. Here, you do not care about the internal processing of the message delivery. Abstraction can be achieved using Abstract Class and Abstract Method in Java.

Abstract Class is a class which is declared “abstract” is called as an abstract class. It can have abstract methods as well as concrete methods. A normal class cannot have abstract methods.

Abstract Method is a method without a body is known as an Abstract Method. It must be declared in an abstract class. The abstract method will never be final because the abstract class must implement all the abstract methods.

What are the rules of Abstract Method?

  1. Abstract methods do not have an implementation; it only has method signature
  2. If a class is using an abstract method they must be declared abstract. The opposite cannot be true. This means that an abstract class does not necessarily have an abstract method.
  3. If a regular class extends an abstract class, then that class must implement all the abstract methods of the abstract parent

For example, take this class representing an Angle:

public class Angle 
{
     private double angleInDegrees;
     private double angleInRadians;
     public static Angle angleFromDegrees(double degrees)
     {
         Angle a = new Angle();
         a.angleInDegrees = degrees;
         a.angleInRadians = Math.PI*degrees/180;
         return a;
     }
     public static Angle angleFromRadians(double radians)
     {
         Angle a = new Angle();
         a.angleInRadians = radians;
         a.angleInDegrees = radians*180/Math.PI;
         return a;
     }
     public double getDegrees()
     {
         return angleInDegrees;
     }
     public double getRadians()
     {
         return angleInRadians;
     }
     public void setDegrees(double degrees)
     {
         this.angleInDegrees = degrees;
         this.angleInRadians = Math.PI*degrees/180;
     }
     public void setRadians(double radians)
     {
         this.angleInRadians = radians;
         this.angleInDegrees = radians*180/Math.PI;
     }
     private Angle(){}
}

This class relies on a basic assumption (or invariant): angleInDegrees and angleInRadians are always in sync. If the class members were public, there would be no guarantees that the two representations of angles are correlated.

Problem we will face if encapsulation is not used

Consider the following Java code example:

public class BadOO 
{
     public int size;
     public int weight;
     ...
}
public class ExploitBadOO 
{
     public static void main (String [] args) 
     {
         BadOO b = new BadOO();
         b.size = -5; // Legal but bad!!
     }
}

And now you are in trouble.

  • How are you going to change the class in a way that lets you handle the issues that come up when somebody changes the size variable to a value that causes problems?

Your only choice is to go back in and write method code for adjusting size (a setSize(int a) method, for example), and then protect the size variable with, say, a private access modifier. But as soon as you make that change to your code, you break everyone else's! The ability to make changes in your implementation code without breaking the code of others who use your code is a key benefit of encapsulation. You want to hide implementation details behind a public programming interface. By interface, we mean the set of accessible methods your code makes available for other code to call. By hiding implementation details, you can rework your method code (perhaps also altering the way variables are used by your class) without forcing a change in the code that calls your changed method.

If you want maintainability, flexibility, and extensibility (and of course, you do), your design must include encapsulation. How do you do that?

  1. Keep instance variables protected (with an access modifier, often private).
  2. Make public accessor methods, and force calling code to use those methods rather than directly accessing the instance variable.

This is a companion discussion topic for the original entry at http://iq.opengenus.org/encapsulation-in-java/