# Object-Oriented Programming: Encapsulation

*Encapsulation* is the process of combining data members (*fields/properties*) and behaviors (*methods/functions*) into a single unit (*class, interface, struct*).

### **Real-world Example**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730335116129/98ac4ce0-2dfc-4849-9730-de0767d02c4d.jpeg align="center")

For example, a Bag and its contents. In this illustration, all the contents of the bag, such as books, pens, rulers, etc., are combined and stored in a bag. We cannot take out the pen, book, and various other items inside the bag without first opening the bag.

### **Code Example**

```csharp
class Bank
{
    public long AccountNumber;
    public string Name;
    public int Balance;

    public void GetBalance()
    {
    }
    public void WithdrawAmount()
    {
    }
    public void Deposit()
    {
    }
}
```

In the example above, the Bank class is an example of *encapsulation*. The data members and *methods* of the class are bound in a single unit, which is the Bank class.

Here, *encapsulation* binds the implementation details of the Bank class. If there is code that wants to access the fields & methods in the Bank class, it must first initialize an object of the Bank class, as shown in the code below.

```csharp
Bank bank = new Bank();
// The property and method below cannot be accessed without first
// declaring an object of the bank class.
bank.AccountNumber = 12345678;
bank.Name = "Kristiadhy";
bank.GetBalance();
bank.WithdrawAmount();
```

### **Data Hiding in Encapsulation**

The biggest advantage of encapsulation is *data hiding*, the process where we hide internal data from the outside world. Data hiding is also known as Data Encapsulation.

To hide and expose data, we need *access modifiers*. *Access Modifiers* are keywords that determine the accessibility level of a class, method, variable, and other members.

In C#, generally, access modifiers can be divided into 4 (although it can be more if combining several access modifiers), for example:

* **Private.**
    
    Members can only be accessed within the class itself.
    
* **Protected.**
    
    Members can be accessed within the class and all its derived classes.
    
* **Internal.**
    
    Members can be accessed within the same *assembly*.
    
* **Public.**
    
    Members can be accessed by the same assembly or different assemblies that reference it.
    

Here is the code example:

```csharp
public class BankDataEncapsulation
{
    // The balance field is hidden from access outside the class
    // by using the private access modifier
    private double balance;

    // Create public Setter and Getter methods
    // Public Getter method
    // This method is used to return the value of the balance variable
    public double GetBalance()
    {
        // We can add validation if necessary    
        return balance;
    }

    // Public Setter Method
    // This method is used to assign a value to the balance variable
    public void SetBalance(double balance)
    {         
        // We can add validation to check
        // whether the input data is correct or not.
        this.balance = balance;
    }
}
```

In the code example above, in the class, we have a field balance set as *private*. The field cannot be accessed by anyone outside its class (even if the class has been initialized as an object). An example can be seen in the code below.

```csharp
BankDataEncapsulation bankEncapsulation = new BankDataEncapsulation();
bankEncapsulation.balance; // This line will result in a compile-time error.
```

So how do we manipulate the balance value in the BankDataEncapsulation class? We can do it by accessing the *getter* and *setter* methods that have been set as *public*. Please see the code example below.

```csharp
BankDataEncapsulation bankEncapsulation = new BankDataEncapsulation();
bankEncapsulation.SetBalance(500);
Console.WriteLine(bankEncapsulation.GetBalance());
```

This way, the balance field is safe and locked so that its value cannot be changed except by the methods allowed by the class through certain *access modifiers*. This ensures data security.

Additionally, when we want to add validation to the balance value, we can add it by modifying the *getter* and *setter* methods, so we don't need to change the code when calling the method. Here is the code example.

```csharp
    public double GetBalance()
    {
        // In the getter method, we add validation.
        if(balance > 1000000)
            throw new Exception("Anda tidak bisa cek saldo diatas 1000000");  
    
        return balance;
    }

    public void SetBalance(double balance)
    {         
        // We also add validation in the setter method.
        if(balance < 0)
            throw new Exception("Saldo tidak boleh negatif");

        this.balance = balance;
    }
```

We can see that even though there is additional *logic* in both methods, the code when calling the method remains the same/unchanged, still like this.

```csharp
BankDataEncapsulation bankEncapsulation = new BankDataEncapsulation();
bankEncapsulation.SetBalance(500);
Console.WriteLine(bankEncapsulation.GetBalance());
```

This is very advantageous because we don't need to make many adjustments when there is a change in *logic*. This is a simple example of the benefits of the *Encapsulation* concept.

### **Some Benefits of Encapsulation**

* **Data Protection.**
    
    We can validate data before storing it in a variable.
    
* **Data Hiding.**
    
    The *caller* will not know about the implementation of the parts inside the class.
    
* **Security.**
    
    The principle of encapsulation helps secure our code by ensuring that other units (class, interface, etc.) cannot access data directly.
    
* **Flexibility.**
    
    The principle of encapsulation makes our code more flexible, allowing programmers to easily change or update the code.
    
* **Control.**
    
    The principle of encapsulation provides greater control over the data stored in variables. For example, we can control data by validating whether it is good enough to be stored in a variable.
    

We have learned about one of the concepts of the 4 pillars of OOP, which is ***Encapsulation***. Next, we will learn about another concept in OOP, which is [***Polymorphism***](https://kristiadhy.hashnode.dev/oop-polymorphism).
