😽Encapsulation

Encapsulation is one of the fundamental concepts of object-oriented programming (OOP). It refers to the practice of bundling data and the methods that operate on that data, within a single unit or entity, called a class. Encapsulation allows us to hide the implementation details of a class from the user, by providing a well-defined interface for accessing and modifying its data.

The main idea behind encapsulation is to protect the internal state of an object from being modified by external code. This is achieved by making the internal data members of a class private, so that they can only be accessed or modified through public methods provided by the class. These public methods are known as getters and setters, and they allow the user to access and modify the internal state of the object in a controlled manner.

Encapsulation is important for several reasons:

  1. Data hiding: Encapsulation allows us to hide the implementation details of a class from the user, which reduces the complexity of the code and makes it easier to maintain and modify.

  2. Security: By controlling the access to the internal data members of a class, we can ensure that the data is not modified in unexpected ways, which can help prevent security vulnerabilities.

  3. Reusability: Encapsulation promotes code reusability, as classes can be used as building blocks for other classes and applications.

  4. Polymorphism: Encapsulation is a key factor in achieving polymorphism, which is the ability of objects to take on different forms or behaviors depending on their context.

Access Modifiers in Python

Python doesn't have access modifiers like other object-oriented programming languages such as Java or C++. In Python, there are no keywords such as private, public, or protected to restrict access to class attributes and methods.

However, there are conventions that are used to indicate the accessibility of an attribute or method:

  • _attribute: A single underscore prefix is used to indicate that an attribute or method is intended for internal use only, and should not be accessed from outside the class. However, there is no actual restriction on accessing these attributes or methods.

  • __attribute: A double underscore prefix invokes name mangling, which changes the name of the attribute to _classname__attribute. This is used to avoid naming conflicts between attributes in different classes that have the same name. This also prevents accidental modification of attributes that are intended to be used only within the class.

  • __method: A double underscore prefix is used to define a private method, which can only be accessed within the class. Like with double underscore attributes, name mangling is used to change the name of the method to _classname__method.

It's important to note that these conventions are not enforced by the Python language itself, and can be bypassed if necessary. The conventions are simply a way to indicate the intended use and accessibility of class attributes and methods.

Here are some examples of access modifiers in Python:

  1. Public Access Modifier: Public access modifier is the default access modifier in Python. In this modifier, all the members of the class are accessible from anywhere within the program. Here is an example:

class MyClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y

myObj = MyClass(5, 10)
print(myObj.x) # Output: 5
  1. Private Access Modifier: Private access modifier in Python is denoted by double underscores (__). Members of the class with this modifier are only accessible within the class. Here is an example:

class MyClass:
    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    def display(self):
        print("x:", self.__x)
        print("y:", self.__y)

myObj = MyClass(5, 10)
myObj.display() # Output: x: 5, y: 10
print(myObj.__x) # Error: 'MyClass' object has no attribute '__x'
  1. Protected Access Modifier: Protected access modifier in Python is denoted by single underscore (_). Members of the class with this modifier can be accessed within the class and its subclasses. Here is an example:

class MyClass:
    def __init__(self, x, y):
        self._x = x
        self._y = y

class MySubClass(MyClass):
    def display(self):
        print("x:", self._x)
        print("y:", self._y)

myObj = MySubClass(5, 10)
myObj.display() # Output: x: 5, y: 10

Note that these are just examples, and access modifiers in Python do not work exactly the same way as they do in other programming languages. In Python, there is no true way to enforce private or protected access, and it is up to the programmer to follow naming conventions and best practices.

Public Access Modifier

Public access modifier is the default access modifier in Python. All class members (variables and methods) are public by default, which means they can be accessed from outside the class. Public members can be accessed using the dot (.) operator on an object of the class.

Here's an example of a class with a public member variable and method:

class MyClass:
    # Public member variable
    name = "Rocky"
    
    # Public member method
    def greet(self):
        print(f"Hello, my name is {self.name}.")
        
# Create an object of the class
obj = MyClass()

# Access the public member variable
print(obj.name)

# Call the public member method
obj.greet()

Output:

Rocky
Hello, my name is Rocky.

Protected Access Modifier

In Python, the protected access modifier is achieved by using a single underscore (_) before the attribute or method name. The attribute or method marked as protected can be accessed from within the class and its subclasses.

Here's an example:

class Car:
    def __init__(self):
        self._color = "red"
        
class SportsCar(Car):
    def __init__(self):
        super().__init__()
        print("Sports car created")
        print("Color of sports car:", self._color)

car = Car()
print("Color of car:", car._color)

sports_car = SportsCar()

In the above example, _color is a protected attribute of the Car class. The SportsCar class is a subclass of the Car class and it can access the _color attribute using self._color.

We can also access the _color attribute outside the class using the instance of the class as shown in the last two lines of the code. However, it's important to note that accessing a protected attribute outside the class is not recommended as it goes against the principles of encapsulation.

Encapsulation Example

Here is an example of how encapsulation can be used in Python:

class BankAccount:
    def __init__(self, account_number, balance):
        self.__account_number = account_number
        self.__balance = balance
        
    def get_account_number(self):
        return self.__account_number
    
    def set_balance(self, balance):
        self.__balance = balance
        
    def get_balance(self):
        return self.__balance
    
account = BankAccount("12345", 5000)
print("Account number:", account.get_account_number())
print("Initial balance:", account.get_balance())

account.set_balance(10000)
print("New balance:", account.get_balance())

In this example, we have defined a BankAccount class with two instance variables __account_number and __balance. We have used the double underscore before the variable names to make them private, which means they cannot be accessed from outside the class.

We have also defined two methods get_account_number and set_balance to get and set the values of the private variables respectively. The get_account_number method returns the value of the __account_number variable, while the set_balance method allows us to update the value of the __balance variable.

In the main program, we create an object of the BankAccount class with an account number of "12345" and an initial balance of 5000. We then call the get_account_number and get_balance methods to retrieve the values of the private variables. We also call the set_balance method to update the value of the __balance variable to 10000, and then call the get_balance method again to confirm that the value has been updated.

By encapsulating the __account_number and __balance variables and providing methods to access and update them, we can control how the object's data is accessed and modified from outside the class, which can help to prevent errors and ensure the integrity of the data.

Last updated