Encapsulation
Part of Object-Oriented Programming
What is Encapsulation?
Encapsulation is the bundling of data (attributes) and methods that operate on that data within a single unit (class), while restricting direct access to some components.
It's like a protective wrapper that prevents external code from directly accessing internal data, instead providing controlled access through public methods.
Real-World Analogy
Think of an ATM machine. You can't directly access the cash inside - you must use the interface (card slot, PIN pad, buttons). The ATM validates your request and controls how much you can withdraw. The internal mechanisms are hidden (encapsulated) from you.
Interactive Visualization
Encapsulation Demo: Bank Account
Access Modifiers
Public
- • Accessible from anywhere
- • No restrictions
- • Python:
name - • Java/C++:
public
Protected
- • Class + subclasses
- • Inherited classes can access
- • Python:
_name - • Java/C++:
protected
Private
- • Only within the class
- • Most restrictive
- • Python:
__name - • Java/C++:
private
Code Implementation
# Encapsulation in Python
class BankAccount:
def __init__(self, owner, initial_balance=0):
self.owner = owner # Public attribute
self._account_type = "Savings" # Protected (convention)
self.__balance = initial_balance # Private (name mangling)
# Public methods - the interface
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"Deposited ${amount}. New balance: ${self.__balance}"
return "Invalid amount"
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return f"Withdrew ${amount}. New balance: ${self.__balance}"
return "Insufficient funds or invalid amount"
def get_balance(self): # Getter
return self.__balance
# Using @property decorator (Pythonic way)
@property
def balance(self):
return self.__balance
@balance.setter
def balance(self, value):
if value >= 0:
self.__balance = value
else:
raise ValueError("Balance cannot be negative")
# Usage
account = BankAccount("Alice", 1000)
# Public access works
print(account.owner) # Alice
print(account.deposit(500)) # Deposited $500. New balance: $1500
# Direct access to private fails
# print(account.__balance) # AttributeError!
# Use public methods instead
print(account.get_balance()) # 1500
print(account.balance) # 1500 (using property)
# Attempting to set invalid balance
# account.balance = -100 # ValueError: Balance cannot be negativeBenefits of Encapsulation
Data Protection
Prevents accidental or malicious modification of data. Balance can't be set to negative values if the setter validates it.
Flexibility
Internal implementation can change without affecting external code. You could change from storing cents to dollars internally.
Easier Debugging
If data becomes invalid, you know it happened through a setter - easier to find the bug than if any code could modify the data.
Clear Interface
Public methods define a clear API. Users of the class know exactly what operations are available and supported.
Common Mistakes
Making everything public
Exposing all attributes as public defeats the purpose of encapsulation. Think about what really needs to be accessible from outside.
Getters/setters without validation
If your setter just assigns the value without validation, you might as well make the attribute public. Add meaningful validation logic.
Returning mutable objects directly
If you return a list or object reference, the caller can modify it. Return a copy instead: return self.__items.copy()
Interview Tips
Test Your Knowledge
Encapsulation Quiz
Question 1 of 6What is encapsulation in OOP?