OOP Fundamentals

Encapsulation

Bundling data and methods that operate on that data within a single unit, and restricting direct access to some of the object's components.

10 min readEssential

1What is Encapsulation?

๐ŸŽฏ Real-World Analogy
๐Ÿ’Š
Medicine Capsule

A capsule encapsulates medicine inside. You don't touch the medicine directly - you take the whole capsule. The outer shell protects the contents and controls how you interact with it.

๐Ÿš—
Car Dashboard

You interact with the car through steering wheel, pedals, and buttons. You don't directly access the engine, fuel injection, or transmission. The interface hides the complex implementation.

Encapsulation is the bundling of data (attributes) and methods (behaviors) that operate on that data into a single unit (class), and restricting direct access to some components. It's achieved through access modifiers (private, protected, public) andgetters/setters.

The Encapsulation Boundary

CLASS BOUNDARY
๐Ÿ”’ Private (Hidden)
- balance: double
- password: string
- validatePin()
๐Ÿ”“ Public (Accessible)
+ getBalance()
+ deposit(amount)
+ withdraw(amount)
๐Ÿ‘ค
External
Code
External code can only access public members, not private internals.

2Why Do We Need Encapsulation?

๐Ÿ›ก๏ธ
Data Protection
Prevent invalid data from corrupting object state. Validate before accepting.
๐Ÿ”ง
Controlled Access
Decide what can be read, what can be modified, and how.
๐Ÿ”„
Flexibility to Change
Change internal implementation without affecting external code.
๐Ÿงช
Easier Testing
Test through public interface. Internal details are isolated.

Without vs With Encapsulation

โŒ Without Encapsulation
// Anyone can do anything!
account.balance = -1000;
account.password = "";
// ๐Ÿ’ฅ Data corruption!
  • No validation
  • Invalid states possible
  • Can't change internals later
โœ… With Encapsulation
// Controlled access
account.withdraw(1000);
// โœ… Validates first!
// Returns false if invalid
  • Validation enforced
  • Invalid states prevented
  • Can change internals safely

3Access Modifiers

Access modifiers control the visibility of class members. Different languages have different modifiers:

ModifierSame ClassSubclassSame PackageOutside
privateโœ…โŒโŒโŒ
protectedโœ…โœ…โœ…โŒ
default (package)โœ…โš ๏ธโœ…โŒ
publicโœ…โœ…โœ…โœ…
Java
private, protected, public, (default)
Python
_ (protected), __ (private by convention)
C++
private, protected, public

4Implementing Encapsulation

The classic pattern: private fields + public getters/setters with validation.

BankAccount with Proper Encapsulation
public class BankAccount {
    // ========== PRIVATE FIELDS (Hidden) ==========
    private String accountNumber;
    private String holderName;
    private double balance;
    private String pin;

    // ========== CONSTRUCTOR ==========
    public BankAccount(String accountNumber, String holderName, String pin) {
        this.accountNumber = accountNumber;
        this.holderName = holderName;
        this.balance = 0.0;
        setPin(pin); // Use setter for validation
    }

    // ========== GETTERS (Controlled Read Access) ==========
    
    public String getAccountNumber() {
        // Return masked version for security
        return "****" + accountNumber.substring(accountNumber.length() - 4);
    }

    public String getHolderName() {
        return holderName;
    }

    public double getBalance() {
        return balance; // Read-only access
    }

    // No getPin() - password should never be exposed!

    // ========== SETTERS (Controlled Write Access) ==========
    
    public void setHolderName(String name) {
        if (name == null || name.trim().isEmpty()) {
            throw new IllegalArgumentException("Name cannot be empty");
        }
        this.holderName = name.trim();
    }

    private void setPin(String pin) {
        if (pin == null || pin.length() != 4 || !pin.matches("\\d+")) {
            throw new IllegalArgumentException("PIN must be 4 digits");
        }
        this.pin = pin;
    }

    // No setBalance() - balance can only change via deposit/withdraw!

    // ========== BUSINESS METHODS (Controlled Operations) ==========
    
    public boolean deposit(double amount) {
        if (amount <= 0) {
            System.out.println("Deposit amount must be positive");
            return false;
        }
        this.balance += amount;
        System.out.println("Deposited: " + amount + ", New Balance: " + balance);
        return true;
    }

    public boolean withdraw(double amount, String enteredPin) {
        // Validate PIN first
        if (!this.pin.equals(enteredPin)) {
            System.out.println("Invalid PIN!");
            return false;
        }
        
        // Validate amount
        if (amount <= 0) {
            System.out.println("Amount must be positive");
            return false;
        }
        
        if (amount > balance) {
            System.out.println("Insufficient funds!");
            return false;
        }
        
        this.balance -= amount;
        System.out.println("Withdrawn: " + amount + ", Remaining: " + balance);
        return true;
    }
}

// ========== USAGE ==========
BankAccount account = new BankAccount("1234567890", "Alice", "1234");

// โœ… Valid operations through public interface
account.deposit(1000);
account.withdraw(200, "1234");
System.out.println("Balance: " + account.getBalance());

// โŒ These would NOT compile - fields are private!
// account.balance = 1000000;  // Can't access!
// account.pin = "0000";        // Can't access!
// String pin = account.pin;    // Can't access!

5Getters & Setters Best Practices

โœ… DO: Add validation in setters
Check for null, range, format before accepting values
โœ… DO: Return defensive copies for mutable objects
Return new ArrayList(list) instead of the original list
โœ… DO: Make fields private by default
Only expose what's necessary through public methods
โŒ DON'T: Don't create getters/setters for everything automatically
Only expose what the outside world actually needs
โŒ DON'T: Don't expose internal data structures directly
Return unmodifiable views or copies instead
โŒ DON'T: Don't have setters for derived/calculated values
getAge() should calculate from birthDate, not be settable
๐Ÿ’ก When NOT to use getters/setters
If a getter just returns a value and setter just assigns it with no validation, consider if you really need encapsulation for that field. Sometimes a simple public field is fine for data transfer objects (DTOs).

6Interview Questions

โ“ What is encapsulation and why is it important?
Encapsulation bundles data and methods together while restricting direct access to internal data. It's important because it: 1) Protects data integrity through validation, 2) Hides implementation details allowing changes without affecting clients, 3) Provides controlled access through public interface, 4) Reduces coupling between classes.
โ“ What's the difference between encapsulation and abstraction?
Encapsulation is about hiding DATA (making fields private, using getters/setters). Abstraction is about hiding IMPLEMENTATION COMPLEXITY (showing 'what' not 'how'). Encapsulation is a mechanism to achieve abstraction. Example: private balance with public deposit() is encapsulation; the fact that deposit() handles logging, validation, notifications internally is abstraction.
โ“ Why shouldn't we just make all fields public with getters/setters?
1) Blind getters/setters defeat the purpose - no validation happens. 2) It exposes internal structure - harder to change later. 3) Not all fields should be readable or writable. 4) Some operations should be methods, not setters (use withdraw() not setBalance()). Only create accessors for fields that truly need external access.

7Key Takeaways

1Encapsulation bundles data + methods and restricts direct access to internals.
2Use private fields + public methods to control access.
3Getters provide read access; setters provide validated write access.
4Not every field needs a getter/setter - only expose what is necessary.
5Encapsulation allows you to change internals without breaking external code.
6It protects data integrity by enforcing validation rules.