# Encapsulation and Abstraction — The Difference, Explained Simply

Source: https://skills101.in/learn/oops/encapsulation-and-abstraction — Skills101 free tutorial (OOP Concepts). Updated 2026-11-09.

These two pillars are often confused. In one line each:

- **Encapsulation** = **protect the data** (keep it private; allow access only through methods).
- **Abstraction** = **hide the complexity** (users see a simple interface, not the inner workings).

## 1. Encapsulation

![A capsule holding the private balance of 1000; outside code can only reach it through deposit(), withdraw() and balance(), which check the rules](https://skills101.in/learn-img/oops/encapsulation.svg)

Without encapsulation, any code could write `account.balance = -500`. With it, the class **guards its own rules**.

```python
class BankAccount:
    def __init__(self, owner):
        self.owner = owner
        self.__balance = 0          # double underscore: name-mangled, "private"

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("deposit must be positive")
        self.__balance += amount

    def withdraw(self, amount):
        if amount > self.__balance:
            return "Insufficient balance"
        self.__balance -= amount
        return f"Withdrew {amount}"

    @property
    def balance(self):              # read-only access
        return self.__balance

acc = BankAccount("Asha")
acc.deposit(1000)
print(acc.withdraw(300), acc.balance)
print(acc.withdraw(5000))
try:
    acc.__balance = -500            # creates a NEW attribute; the real balance is safe
    print(acc.balance)
except AttributeError as e:
    print(e)
```

```text
Withdrew 300 700
Insufficient balance
700
```

Java does it with the `private` keyword and getters/setters:

```java
class Student {
    private int marks;                       // hidden
    public int getMarks() { return marks; }
    public void setMarks(int m) {
        if (m < 0 || m > 100) throw new IllegalArgumentException("marks must be 0-100");
        marks = m;
    }
}

public class Main {
    public static void main(String[] args) {
        Student s = new Student();
        s.setMarks(88);
        System.out.println(s.getMarks());
        try {
            s.setMarks(150);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected: " + e.getMessage());
        }
    }
}
```

```text
88
Rejected: marks must be 0-100
```

**Benefits:** data stays valid, internal code can change without breaking users, easier debugging (only one place changes the data).

## 2. Abstraction

![A TV remote shows only Power, Volume and Channel buttons, while the IR signals, circuits and decoders stay hidden behind an interface](https://skills101.in/learn-img/oops/abstraction.svg)

Abstraction is about **design**: what should users of this class see? In code, it's usually done with **abstract classes** or **interfaces** that define *what* must be done, leaving *how* to the concrete classes.

```python
from abc import ABC, abstractmethod

class Notifier(ABC):
    @abstractmethod
    def send(self, to, text):
        """Every notifier must know how to send."""

class SmsNotifier(Notifier):
    def send(self, to, text):
        return f"SMS to {to}: {text}"

class EmailNotifier(Notifier):
    def send(self, to, text):
        return f"Email to {to}: {text}"

def remind(notifier: Notifier, to):
    # this function doesn't know or care HOW the message goes out
    return notifier.send(to, "Your mock test starts at 6 pm")

print(remind(SmsNotifier(), "98290xxxxx"))
print(remind(EmailNotifier(), "asha@x.in"))
try:
    Notifier()
except TypeError:
    print("Can't create an abstract Notifier")
```

```text
SMS to 98290xxxxx: Your mock test starts at 6 pm
Email to asha@x.in: Your mock test starts at 6 pm
Can't create an abstract Notifier
```

Tomorrow you can add `WhatsAppNotifier` — `remind()` doesn't change at all.

## 3. The difference (interview answer)

| | Encapsulation | Abstraction |
|---|---|---|
| Goal | **protect** data | **hide complexity** |
| Question it answers | "who can change this data?" | "what does the user need to see?" |
| How | private fields + methods | abstract classes, interfaces |
| Level | implementation | design |
| Example | `balance` is private | `Notifier.send()` hides SMS/email details |

They work together: abstraction decides the **public face**; encapsulation **locks** the inside.

## Common mistakes

- Saying they're the same thing.
- Making fields private but adding a setter with **no checks** — that's not real protection.
- Thinking Python has truly private variables (it has conventions: `_x` internal, `__x` name-mangled).

## Quick recap

- Encapsulation: private data + controlled methods → data stays valid.
- Abstraction: expose what, hide how → interfaces/abstract classes.
- Encapsulation is about protection; abstraction is about simplicity.


Practice quiz and free certificate: https://skills101.in/learn/oops/encapsulation-and-abstraction