[Python OOP] 4. Encapsulation and Abstraction
4. Encapsulation and Abstraction
This section will delve into more advanced topics of encapsulation and abstraction, two core principles of object-oriented programming that allow us to hide the internal state of an object and expose only what is necessary.
4.1 Advanced Encapsulation
Encapsulation is the mechanism that restricts access to an object’s components, which is a fundamental principle to protect the object’s integrity by preventing outsiders from setting the internal data of the component to an invalid or inconsistent state.
4.1.1 Name Mangling
Name mangling is a technique used in Python to prevent subclass from accidentally overriding the private attributes and methods of a superclass.
class Account:
def __init__(self, balance):
self.__balance = balance # Name mangling
def deposit(self, amount):
if amount > 0:
self.__balance += amount # Accessing the mangled name
def get_balance(self):
return self.__balance
acc = Account(1000)
print(acc.get_balance()) # Output: 1000
print(acc.__balance) # AttributeError: 'Account' object has no attribute '__balance'
4.1.2 Using @property
for Getter and Setter
Python doesn’t have built-in support for private attributes, but we can achieve a similar effect using @property
decorators to create managed attributes, also known as “getters” and “setters”.
class Product:
def __init__(self, price):
self.__price = price
@property
def price(self):
return self.__price
@price.setter
def price(self, value):
if value < 0:
raise ValueError("Price cannot be negative.")
self.__price = value
product = Product(50)
print(product.price) # Output: 50
product.price = 30
print(product.price) # Output: 30
# product.price = -10 # ValueError: Price cannot be negative.
4.2 Implementing Abstraction
Abstraction is an extension of encapsulation. It involves the process of handling complexity by hiding unnecessary details from the user.
4.2.1 Abstract Classes
An abstract class can be considered as a blueprint for other classes. It allows you to create a set of methods that must be created within any child classes built from the abstract class.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
# This will raise an error if instantiated or if the subclass does not implement the abstract methods
# shape = Shape()
4.2.2 Abstract Methods
Abstract methods are those declared in the abstract class, which have no implementation. Subclasses are expected to implement these methods.
class Rectangle(Shape):
def __init__(self, width, height):
self.__width = width
self.__height = height
def area(self):
return self.__width * self.__height
def perimeter(self):
return 2 * (self.__width + self.__height)
rectangle = Rectangle(2, 3)
print(rectangle.area()) # Output: 6
print(rectangle.perimeter()) # Output: 10
Note that we cannot instantiate an abstract class that has abstract methods. This encourages a child class to implement the abstract methods, thus adhering to the abstraction principle.