Introduction
Encapsulation is one of the fundamental concept in object-oriented programming (OOP).
Encapsulation describes bundling data and methods that work on that data within one unit, like a class. We often often use this concept to hide an object’s internal representation or state from the outside. This is called information hiding.
The general idea of this mechanism is simple. For example, you have an attribute that is not visible from the outside of an object. You bundle it with methods that provide read or write access. Encapsulation allows you to hide specific information and control access to the object’s internal state.
If you’re familiar with any object-oriented programming language, you probably know these methods as getter and setter methods. As the names indicate, a getter method retrieves an attribute and a setter method changes it. Depending on the methods that you implement, you can decide if an attribute can be read and changed. You may also control if the attribute is read-only or not visible at all. Later, we’ll show you how you can also use the setter method to implement additional validation rules to ensure that your object always has a valid state.
Data Encapsulation can be defined as wrapping the code or methods(properties) and the related fields or variables together as a single unit. In object-oriented programming, we call this single unit – a class, interface, etc. We can visualize it like a medical capsule (as the name suggests, too), wherein the enclosed medicine can be compared to fields and methods of a class.
Setter and Getter Method
Getter and setter methods are used to access and modify the private variables (fields) of a class, respectively. They help achieve encapsulation by providing controlled access to the class’s attributes.
Example
public class Person {
private String name;
private int age;
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person();
// Set values using setter methods
person.setName("John");
person.setAge(30);
// Retrieve values using getter methods
System.out.println("Name: " + person.getName());
System.out.println("Age: " + person.getAge());
}
}
JavaOutput
Name: John
Age: 30
Java- The
main()
method creates an instance of thePerson
class namedperson
. - The setter methods
setName("John")
andsetAge(30)
are used to set the values of thename
andage
attributes of theperson
object. - The getter methods
getName()
andgetAge()
are used to retrieve the values of thename
andage
attributes, respectively. - The retrieved values are then printed to the console.
Implementation of Encapsulation
Example
public class Person {
private String name;
private int age;
// Constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("Age cannot be negative.");
}
}
// Method to display person details
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
Person person = new Person("John", 30);
// Display initial details
person.display();
// Update name
person.setName("Alice");
// Update age
person.setAge(25);
// Display updated details
person.display();
}
}
JavaOutput
Name: John
Age: 30
Name: Alice
Age: 25
Javaname
andage
are private instance variables, accessible only within thePerson
class.getName()
andsetName()
methods provide access to thename
variable, ensuring encapsulation by controlling how thename
can be accessed and modified.getAge()
andsetAge()
methods provide access to theage
variable, with additional validation to ensure the age is non-negative.display()
method allows displaying the person’s details without exposing the internal implementation.
Data Hiding
Data hiding, also known as information hiding, is a fundamental principle of object-oriented programming and encapsulation . It refers to the concept of hiding the implementation details of a class’s attributes (data) and exposing only the necessary information or interfaces to interact with those attributes.
Data hiding is achieved by declaring class attributes as private, meaning they are accessible only within the class itself. Outside classes cannot directly access or modify these private attributes. Instead, interactions with these attributes are typically mediated through public methods such as getters and setters, which provide controlled access to the data.
Here’s how data hiding works in encapsulation:
- Private Attributes: Attributes of a class are declared as private to restrict direct access from outside the class.
public class Person {
private String name; // private attribute
private int age; // private attribute
// other code...
}
Java- Public Methods: Public methods, such as getters and setters, are provided to access and modify the private attributes.
public class Person {
private String name;
private int age;
// Getter for name
public String getName() {
return name;
}
// Setter for name
public void setName(String name) {
this.name = name;
}
// Getter for age
public int getAge() {
return age;
}
// Setter for age
public void setAge(int age) {
this.age = age;
}
// other code...
}
Java- Controlled Access: Outside classes interact with the object’s attributes only through these public methods. This way, the internal representation of data is hidden, and the class can enforce its own rules and validations.
public class Main {
public static void main(String[] args) {
Person person = new Person();
// Access and modify attributes via public methods
person.setName("John");
person.setAge(30);
// Retrieve attribute values
String name = person.getName();
int age = person.getAge();
// Display information
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
JavaBy hiding the internal implementation details and exposing only a well-defined interface, data hiding enhances encapsulation, promotes code maintainability, and reduces the risk of unintended data corruption or manipulation.
Advantages of Encapsulation
Encapsulation offers several advantages, which can be summarized in bullet points:
- Data Hiding: Encapsulation hides the internal state of objects by making fields private, preventing direct access from outside the class.
- Enhanced Security: With encapsulation, sensitive data can be protected from unauthorized access and modification, enhancing security.
- Modularity and Maintainability: Encapsulation promotes modularity by isolating the implementation details within a class, making it easier to understand, maintain, and modify the codebase.
- Code Reusability: Encapsulation encourages code reuse by allowing classes to be used as components in larger systems without exposing their internal workings.
- Easier Testing: Encapsulation facilitates unit testing by providing clear boundaries between different components of the system, allowing for easier isolation and testing of individual units.
- Flexibility and Evolution: Encapsulation provides flexibility in changing the internal implementation of a class without affecting its external interface, enabling the evolution of the codebase over time.
- Reduced Coupling: Encapsulation reduces coupling between different parts of the system by limiting dependencies on the internal implementation of classes, promoting a more loosely coupled architecture.
- Encapsulation of Invariants: Encapsulation allows the encapsulation of invariants and business rules within a class, ensuring that data remains consistent and valid throughout its lifecycle.
- Facilitates Abstraction: Encapsulation facilitates abstraction by exposing only essential information through well-defined interfaces, hiding unnecessary details and complexity from the users of the class.
- Supports Information Hiding: Encapsulation supports the principle of information hiding, enabling classes to hide their internal implementation details while providing a clear and consistent interface to interact with.
Conclusion
Encapsulation is a fundamental concept in object-oriented programming that promotes the bundling of data and methods within a class while restricting access to the internal state of objects. By hiding implementation details and providing controlled access through well-defined interfaces, encapsulation enhances security, modularity, maintainability, and code reuse, while also facilitating flexibility, abstraction, and reduced coupling. Overall, encapsulation fosters the creation of robust, modular, and maintainable software systems.
Frequently Asked Questions
Encapsulation is a mechanism of bundling the data (attributes) and methods (behaviors) that operate on the data within a single unit, i.e., a class. It involves hiding the internal state of an object and controlling access to it through public methods.
Encapsulation is achieved by declaring class attributes as private and providing public methods (getters and setters) to access and modify these attributes. This way, the internal state of an object is hidden from outside classes, and access to it is controlled.
Encapsulation should be used whenever you want to hide the internal state of an object and provide controlled access to it. It is particularly useful when designing classes that are part of a larger system, as it helps in managing complexity, improving code maintainability, and ensuring data integrity.
While encapsulation can be enforced by making attributes private and providing controlled access through methods, it is still possible to bypass encapsulation using reflection. However, doing so is generally considered bad practice and should be avoided unless absolutely necessary for specific use cases.
One potential drawback of encapsulation is the overhead of creating getter and setter methods for every attribute, which can lead to increased verbosity in the code. Additionally, excessive use of encapsulation can sometimes result in overly complex class designs, making the code harder to understand and maintain.