Encapsulation is the technique of making the fields in a class private and providing access to these fields with the help of public methods.
If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class.
Therefore encapsulation is also referred to as data hiding.
The main benefit of encapsulation is the ability to modify the implemented code without breaking the code of others who use our code. It also provides us with maintainability, flexibility and extensibility to our code.
An interface is a collection of abstract methods. A class implements an interface, thereby inheriting the abstract methods of the interface.
It includes -
Interface cannot be instantiated.
An interface does not contain any constructors.
All the methods in an interface are abstract.
Abstraction solves the problem at design level while encapsulation solves the problem at implementation level.
Abstraction is used for hiding the unwanted data and provide only the required data. On the other hand encapsulation means hiding the code and data into a single unit to protect the data from outside world.
Abstraction lets you focus on what the object does instead of how it does it while Encapsulation means hiding the internal details or mechanics of how an object does something.
For example: Outer Look of a Television i.e. it has a display screen and channel buttons to change channel explains 'abstraction' but inner implementation detail of a television i.e. how CRT and display screen are connected with each other using different circuits explains 'encapsulation'.
Encapsulation means combining the data of our application and its manipulation at one place.
Encapsulation allows the state of an object to be accessed and modified through behaviour.
It reduces the coupling of modules and increases the cohesion inside them.
Encapsulation is nothing but protecting anything which is prone to change. Rational behind encapsulation is that if any functionality which is well encapsulated in code i.e maintained in just one place and not scattered around code is easy to change.
This can be better explained with a simple example of encapsulation in Java. We all know that constructor is used to create object in Java and constructor can accept argument. Suppose we have a class 'Loan' which has a constructor and in various classes we have created instance of 'loan' using this constructor. Now requirements will change and you need to include 'age of borrower' as well while taking loan.
Since this code is not well encapsulated i.e. not confined in one place you need to change at every place where you are calling this constructor i.e. for one change you need to modify several files instead of just one file which is more error prone and tedious. Though it can be done with refactoring feature of advanced IDE it would prove better if we only need to make change at one place.
This is possible if we encapsulate 'Loan' creation logic in one method say 'createLoan()'. The code written for client will call this method and this method internally creates 'Loan' object. in this case you only need to modify this method instead of the whole client code.
class Loan {
private int duration; //private variables examples of encapsulation
private String loan;
private String borrower;
private String salary;
//public constructor can break encapsulation instead use factory method
private Loan(int duration, String loan, String borrower, String salary){
this.duration = duration;
this.loan = loan;
this.borrower = borrower;
this.salary = salary;
}
//no argument constructor omitted here
// create loan can encapsulate loan creation logic
public Loan createLoan(String loanType){
//processing based on loan type and than returning loan object
return loan;
}
}
Below mentioned are few advantages of using encapsulation while writing code in Java or any Object oriented programming language:
Encapsulated Code is more flexible and easy to change with inception of new requirements.
Encapsulation in Java makes unit testing easy.
Encapsulation in Java allows you to control who can access what.
Encapsulation also helps to write immutable class in Java which is a good choice in multi-threading environment.
Encapsulation reduces coupling of modules and increases cohesion inside a module because all the pieces of one thing are encapsulated in one place.
Encapsulation allows you to change one part of code without affecting other part of code.
What should you encapsulate in code?
Anything which can be changed or which is more likely to be changed in near future is candidate of encapsulation. This also helps to write more specific and cohesive code. For instance object creation code, code which can be improved in future like sorting and searching logic.
"Whatever changes encapsulate it" is a famous design principle.
Encapsulation helps in loose coupling and high cohesion of code.
Encapsulation in Java is achieved using access modifiers private, protected and public.
'Factory pattern' and 'singleton pattern' in Java makes good use of encapsulation.
Many design patterns in Java uses encapsulation concept, one of them is 'factory pattern' which is used to create objects.
'Factory pattern' is a better choice then 'new' operator for creating object of those classes whose creation logic can vary and also for creating different implementations of same interface.
'BorderFactory class' of JDK is a good example of encapsulation in Java which creates different types of 'border' and encapsulates creation logic of border.
'Singleton pattern' in Java also encapsulates how you create instance by providing getInstance() method.
Since object is created inside one class and not from any other place in code you can easily change how you create object without effecting other part of code.
The fields of a class can be made read-only or write-only.
A class can have total control over what is stored in its fields.
The users of a class do not know how the class stores its data. A class can change the datatype of a field and users of the class do not need to make any changes to their code.
To achieve encapsulation in Java:
Declare the variables of a class as 'private'.
Provide public setter and getter methods to modify and view the variable's values.
Below given is an example that demonstrates how to achieve Encapsulation in Java:
/* File name : EncapTest_JBK.java */
public class EncapTest{
private String name;
private String idNum;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public String getIdNum(){
return idNum;
}
public void setAge( int newAge){
age = newAge;
}
public void setName(String newName){
name = newName;
}
public void setIdNum( String newId){
idNum = newId;
}
}
The public setXXX() and getXXX() methods are the access points of the instance variables of the EncapTest class. Normally, these methods are referred as getters and setters.
Therefore any class that wants to access the variables should access them through these getters and setters. The variables of the EncapTest class can be accessed as shown below:
/* File name : RunEncap_JBK.java */
public class RunEncap{
public static void main(String args[]){
EncapTest encap = new EncapTest();
encap.setName("Kiran");
encap.setAge(20);
encap.setIdNum("12343ms");
System.out.print("Name : " + encap.getName() + " Age : " + encap.getAge());
}
}
This would produce the following result:
Output:
Name : Kiran Age : 20