Polymorphism in Python
Polymorphism, a fundamental concept in Object-Oriented Programming (OOP), allows objects of various classes to be considered as objects of a common base class. This promotes flexibility and enables programming to change dynamically dependent on the type of object with which it interacts. Let's look at polymorphism in the context of an Audition Manager by using the User, AdminUser, and ManagerUser classes:
Base Class: User
class AdminUser(User):
def __init__(self, user_id, username, email, password, role):
super().__init__(user_id, username, email, password)
self._role = role
def promote_to_admin(self):
print(f"User {self._username} promoted to admin.")
# Overriding the display_info method for AdminUser
def display_info(self):
print(f"Admin User - User ID: {self._user_id}, Username: {self._username}, Email: {self._email}, Role: {self._role}")
# Create a regular user
regular_user = User(1, "JohnDoe", "john.doe@email.com", "secret_password")
# Create an admin user
admin_user = AdminUser(2, "AdminJohn", "admin.john@email.com", "admin_password", "Administrator")
# Display user information
regular_user.display_info()
# Output: User ID: 1, Username: JohnDoe, Email: john.doe@email.com
admin_user.display_info()
# Output: Admin User - User ID: 2, Username: AdminJohn, Email: admin.john@email.com, Role: Administrator
# Promote the admin user
admin_user.promote_to_admin()
# Output: User AdminJohn promoted to admin.
Derived Class 1: AdminUser
class AdminUser(User):
def __init__(self, user_id, username, email, password, role):
super().__init__(user_id, username, email, password)
self._role = role
def promote_to_admin(self):
print(f"User {self._username} promoted to admin.")
# Overriding the display_info method for AdminUser
def display_info(self):
print(f"Admin User - User ID: {self._user_id}, Username: {self._username}, Email: {self._email}, Role: {self._role}")
Derived Class 2: ManagerUser
class ManagerUser(User):
def __init__(self, user_id, username, email, password, role):
super().__init__(user_id, username, email, password)
self._auditions = [] # List to store auditions created by this manager
def promote_to_manager(self):
print(f"User {self._username} promoted to manager.")
def create_audition(self, audition_name, description, deadline):
new_audition = Audition(audition_name, description, deadline, manager=self)
self._auditions.append(new_audition)
print(f"Audition '{audition_name}' created successfully.")
return new_audition
def get_auditions(self):
return self._auditions
# Additional methods for audition management:
def get_applications(self, audition):
# Retrieve applications for the specified audition
return audition.get_applications() # Assuming Audition class has a method to access applications
def review_application(self, application):
# Implement logic for reviewing an application
pass
def approve_application(self, application):
# Implement logic for approving an application
pass
def reject_application(self, application):
# Implement logic for rejecting an application
pass
def display_info(self):
print(f"Manager User - User ID: {self._user_id}, Username: {self._username}, Email: {self._email}")
Polymorphism in Action: Audition Manager Scenario
Now, let's see how polymorphism allows us to interact with different user types seamlessly:
# Create instances of different user types
regular_user = User(1, "JohnDoe", "john.doe@email.com", "secret_password")
admin_user = AdminUser(2, "AdminJohn", "admin.john@email.com", "admin_password", "Administrator")
manager_user = ManagerUser(3, "ManagerJane", "manager.jane@email.com", "manager_password", "Casting Department")
# Display user information using polymorphism
users = [regular_user, admin_user, manager_user]
for user in users:
user.display_info()
Key Concepts:
display_info
method).User
): Common characteristics and methods shared among different user types.AdminUser
, ManagerUser
): Specialized classes that inherit and extend the functionality of the base class.The SOLID
principle related to polymorphism is the "Liskov Substitution Principle" (L in SOLID
).
The Liskov Substitution Principle states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. This principle directly supports the idea of polymorphism.
Polymorphism allows objects of different types to be treated as objects of a common type, and the Liskov Substitution Principle ensures that this substitution can happen seamlessly. It encourages the use of a common interface or base class so that different implementations (subclasses) can be used interchangeably, promoting flexibility and extensibility in the codebase.