Encapsulation is one of the four fundamental principles of Object-Oriented Programming (OOP), along with inheritance, polymorphism, and abstraction. It is a mechanism that bundles the data (attributes) and methods (functions) that operate on the data into a single unit, typically a class. This concept is crucial for maintaining a modular and manageable codebase.
Definition: Encapsulation is the process of bundling the data (attributes) and the methods (functions) that manipulate that data into a single unit, such as a class. It restricts direct access to some of an object’s components, which is a means of preventing accidental interference and misuse of the data.
Attributes and Methods:
Access specifiers, also known as access modifiers, are keywords used to set the accessibility of classes, methods, and other members. They enforce encapsulation by restricting access to the internal state of an object.
class Example:
def __init__(self):
self.public_attribute = "I am public"
def public_method(self):
return "This is a public method"
obj = Example()
print(obj.public_attribute) # Accessible
print(obj.public_method()) # Accessible
_
prefix in languages like Python.class Example:
def __init__(self):
self._protected_attribute = "I am protected"
def _protected_method(self):
return "This is a protected method"
class SubExample(Example):
def access_protected(self):
return self._protected_method()
obj = SubExample()
print(obj._protected_attribute) # Accessible but intended for internal use
print(obj.access_protected()) # Accessible through a method
__
prefix in languages like Python.class Example:
def __init__(self):
self.__private_attribute = "I am private"
def __private_method(self):
return "This is a private method"
def access_private(self):
return self.__private_method()
obj = Example()
# print(obj.__private_attribute) # Not accessible directly
print(obj.access_private()) # Accessible through a public method
Bank Account Example: Encapsulation can be demonstrated using a BankAccount
class that hides its internal state from the outside world.
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner # Public attribute
self.__balance = balance # Private attribute
def deposit(self, amount):
if amount > 0:
self.__balance += amount
return f"${amount} deposited. New balance: ${self.__balance}"
return "Invalid deposit amount"
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
return f"${amount} withdrawn. New balance: ${self.__balance}"
return "Invalid or insufficient funds"
def get_balance(self):
return self.__balance
# Creating a bank account object
account = BankAccount("Alice", 1000)
# Accessing public attribute
print(account.owner) # Output: Alice
# Accessing private attribute (not directly accessible)
# print(account.__balance) # This will raise an AttributeError
# Using methods to interact with private attribute
print(account.deposit(500)) # Output: $500 deposited. New balance: $1500
print(account.withdraw(200)) # Output: $200 withdrawn. New balance: $1300
print(account.get_balance()) # Output: 1300
Encapsulation is a fundamental principle of OOP that helps manage complexity, enhance security, and improve maintainability in software systems. By bundling data and methods into classes and using access specifiers to control access, developers can create robust, modular, and scalable applications.