Unit 5
ePortfolio activity: Polymorphism
An example of a Python program which uses polymorphism is shown below.
class Cat:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def info(self):
        print(f"I am a cat. My name is {self.name}. I am {self.age} years old.")
    def make_sound(self):
        print("Meow")
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def info(self):
        print(f"I am a dog. My name is {self.name}. I am {self.age} years old.")
    def make_sound(self):
        print("Bark")
cat1 = Cat("Kitty", 2.5)
dog1 = Dog("Fluffy", 4)
for animal in (cat1, dog1):
    animal.make_sound()
    animal.info()
    animal.make_sound()
Source: Programiz. (n.d.) Polymorphism in Python.
Write a Python program with polymorphism that is usable within the summative assessment for the humanoid robot.
The program below demonstrates how the use of polymorphism allows to define a base Robot class and its core behavior and then override it in the implementation classes to enable each robot type to perform specific tasks.
Polymorphism allows to specify the overall interface for interacting with a robot instance and also the common traits of a robot, thus reducing the amount of duplicated code and streamlining the implementation of the derived classes. It is therefore possible to interact with robots of different types using the same methods like greet(), report_status(), or perform_task(). Besides, core logic for performing a task (updating the status before and after a task is executed) is contained in the perform_task() method of the base class, whereas the type-specific behavior is specified in the overridable method _execute_task().
Polymorphism is a powerful tool that boosts the development process by facilitating code reuse.
from enum import Enum
class RobotStatus(Enum):
    """
    Enum for robot status states
    """
    IDLE = "IDLE"
    BUSY = "BUSY"
    OFFLINE = "OFFLINE"
class Task:
    """
    Represents a task that can be assigned to any robot
    """
    def __init__(self, task_id: int, description: str):
        self.task_id = task_id
        self.description = description
    def get_details(self) -> str:
        """Returns formatted task details"""
        return f"Task #{self.task_id}: {self.description}"
class Robot:
    """
    Base class for all robot types
    This class defines the common interface that all robot types will implement.
    Each derived class will override these methods with its own implementation,
    demonstrating polymorphism.
    """
    __next_id = 1
    def __init__(self, name: str):
        """Initialize a robot with a unique ID and default status"""
        self.robot_id = Robot.__next_id
        Robot.__next_id += 1
        self.name = name
        self.status = RobotStatus.IDLE
        self.counter = 0  # Generic counter for tasks/activities
    def greet(self) -> str:
        """
        Returns a greeting message
        This method will be overridden by subclasses to provide
        type-specific greetings.
        """
        return f"Hello, I am robot {self.name}."
    def perform_task(self, task: Task) -> str:
        """
        Performs a given task
        This method handles the common status changes and counter increment,
        while delegating the specific task implementation to _execute_task.
        Subclasses should override _execute_task instead of this method.
        """
        self.status = RobotStatus.BUSY
        result = self._execute_task(task)
        self.counter += 1
        self.status = RobotStatus.IDLE
        return result
    def _execute_task(self, task: Task) -> str:
        """
        Executes the specific task implementation
        This protected method should be overridden by subclasses to provide
        type-specific task handling.
        """
        return f"Robot {self.name} is performing task: {task.get_details()}"
    def report_status(self) -> str:
        """
        Reports the current status of the robot
        This method will be overridden by subclasses to provide
        type-specific status reporting.
        """
        return f"Robot {self.name} is currently {self.status.value}."
class ServiceRobot(Robot):
    """
    Service robot for customer assistance
    """
    def __init__(self, name: str, service_area: str):
        """Initialize with service area"""
        super().__init__(name)
        self.service_area = service_area
    def greet(self) -> str:
        return f"Hello! I'm {self.name}, your service assistant in the {self.service_area}."
    def _execute_task(self, task: Task) -> str:
        return f"Service robot {self.name} is assisting with: {task.get_details()}"
    def report_status(self) -> str:
        return f"Service robot {self.name} is {self.status.value}. Customers served: {self.counter}."
class SecurityRobot(Robot):
    """
    Security robot for surveillance
    """
    def __init__(self, name: str, security_clearance: int):
        """Initialize with security clearance level"""
        super().__init__(name)
        self.security_clearance = min(max(security_clearance, 1), 5)
    def greet(self) -> str:
        return f"Security unit {self.name} active. Clearance level: {self.security_clearance}."
    def _execute_task(self, task: Task) -> str:
        return f"Security robot {self.name} responding to: {task.get_details()}"
    def report_status(self) -> str:
        return f"Security robot {self.name} is {self.status.value}. Alerts handled: {self.counter}."
class MaintenanceRobot(Robot):
    """
    Maintenance robot for repairs
    Demonstrates polymorphism by overriding the base Robot class methods
    with maintenance-specific implementations.
    """
    def __init__(self, name: str, specialization: str):
        """Initialize with repair specialization"""
        super().__init__(name)
        self.specialization = specialization
    def greet(self) -> str:
        return f"Maintenance unit {self.name} online. Specialized in {self.specialization} repairs."
    def _execute_task(self, task: Task) -> str:
        return f"Maintenance robot {self.name} fixing: {task.get_details()}"
    def report_status(self) -> str:
        return f"Maintenance robot {self.name} is {self.status.value}. Repairs completed: {self.counter}."
def main():
    robots = [
        ServiceRobot("Servy", "Restaurant"),
        SecurityRobot("Guard-X", 3),
        MaintenanceRobot("Fixy", "Electrical")
    ]
    tasks = [
        Task(1, "Welcome guests and take orders"),
        Task(2, "Investigate suspicious activity in sector 7"),
        Task(3, "Repair malfunctioning light fixture")
    ]
    # Demonstrate polymorphism by calling the same methods on different robot types
    # Each robot will respond with its own implementation of the method
    print("=== Robot Greetings ===")
    for robot in robots:
        # The same greet() method call works differently for each robot type
        print(robot.greet())
    print("\n=== Task Assignment ===")
    for robot, task in zip(robots, tasks):
        # The same perform_task() method call works differently for each robot type
        print(robot.perform_task(task))
    print("\n=== Status Reports ===")
    for robot in robots:
        # The same report_status() method call works differently for each robot type
        print(robot.report_status())
if __name__ == "__main__":
    main()