Search This Blog

Polymorphism in Python

 

Polymorphism in Python

Polymorphism is another key concept in Object-Oriented Programming (OOP). It comes from the Greek words "poly" (many) and "morph" (form), meaning many forms. Polymorphism allows different classes to be treated as instances of the same class through inheritance. It enables objects of different classes to respond to the same method or function call in their own unique ways.

Polymorphism can be achieved in Python through:

  1. Method Overriding: Where a method in the child class overrides a method in the parent class.
  2. Method Overloading: Python does not support traditional method overloading (like other languages), but similar functionality can be achieved using default arguments or variable-length argument lists.

Polymorphism is one of the pillars of OOP, alongside Encapsulation, Abstraction, and Inheritance. It promotes flexibility and allows code to be written in a more general way, which can work with objects of different types.


1. Polymorphism with Method Overriding

Method overriding occurs when a subclass defines a method that has the same name and parameters as a method in the parent class. When you call the method on an object of the subclass, the subclass’s version of the method is executed, not the parent class’s version.

Example of Method Overriding:

# Parent class
class Animal:
    def speak(self):
        print("Animal makes a sound.")

# Child class
class Dog(Animal):
    def speak(self):
        print("Dog barks.")

# Child class
class Cat(Animal):
    def speak(self):
        print("Cat meows.")

# Polymorphism in action
animals = [Dog(), Cat()]

for animal in animals:
    animal.speak()

Output:

Dog barks.
Cat meows.

In this example:

  • Both Dog and Cat override the speak() method of the Animal class.
  • Even though animals is a list of Animal objects, each object (whether a Dog or a Cat) calls its own version of the speak() method, demonstrating polymorphism.

2. Polymorphism with Inheritance

Polymorphism is often used in combination with inheritance, allowing a subclass to provide a specific implementation for a method defined in a parent class. The same method name can perform different tasks depending on the object that invokes it.

Example of Polymorphism with Inheritance:

# Parent class
class Vehicle:
    def start(self):
        print("Starting the vehicle")

# Child class 1
class Car(Vehicle):
    def start(self):
        print("Starting the car")

# Child class 2
class Bike(Vehicle):
    def start(self):
        print("Starting the bike")

# Demonstrating polymorphism
vehicles = [Car(), Bike()]

for vehicle in vehicles:
    vehicle.start()

Output:

Starting the car
Starting the bike

In this case:

  • The start() method is overridden in both Car and Bike classes.
  • The method call vehicle.start() is resolved based on the actual type of the object, not the reference type, demonstrating polymorphism in action.

3. Polymorphism with Duck Typing

Python is a dynamically typed language, meaning that you don't need to explicitly declare a variable's type. Polymorphism in Python is often referred to as duck typing, which means that if an object behaves like a certain type (i.e., has the necessary methods and properties), it can be used as that type, regardless of its actual class.

Duck Typing is a principle that states: "If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck."

Example of Duck Typing:

class Dog:
    def speak(self):
        print("Dog barks.")

class Bird:
    def speak(self):
        print("Bird chirps.")

class Human:
    def speak(self):
        print("Human talks.")

def animal_sound(animal):
    animal.speak()

# Demonstrating polymorphism with duck typing
animals = [Dog(), Bird(), Human()]

for animal in animals:
    animal_sound(animal)

Output:

Dog barks.
Bird chirps.
Human talks.

In this example:

  • The animal_sound() function accepts any object that has a speak() method. It doesn't matter whether the object is an instance of Dog, Bird, or Human.
  • As long as the object has the required method, Python allows the method to be called, demonstrating polymorphism through duck typing.

4. Polymorphism with Operator Overloading

In Python, you can define how operators behave for your custom objects. This is called operator overloading. For example, you can define the + operator for a class so that it adds two objects of that class in a custom way.

Example of Operator Overloading:

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

    # Overloading the '+' operator
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __repr__(self):
        return f"Point({self.x}, {self.y})"

# Creating two Point objects
p1 = Point(1, 2)
p2 = Point(3, 4)

# Using the overloaded '+' operator
p3 = p1 + p2

print(p3)  # Output: Point(4, 6)

In this example:

  • The + operator has been overloaded by defining the __add__() method in the Point class.
  • When two Point objects are added together using the + operator, the custom behavior defined in __add__() is used, returning a new Point object.

5. Polymorphism with Abstract Classes and Interfaces

Polymorphism can also be implemented using abstract classes and interfaces. An abstract class is a class that cannot be instantiated on its own but is meant to be subclassed. It can define abstract methods, which must be implemented by its subclasses. This allows different subclasses to provide their own implementation for the abstract methods, achieving polymorphism.

Example of Abstract Classes and Polymorphism:

from abc import ABC, abstractmethod

# Abstract class
class Animal(ABC):
    @abstractmethod
    def speak(self):
        pass

# Subclass 1
class Dog(Animal):
    def speak(self):
        print("Dog barks.")

# Subclass 2
class Cat(Animal):
    def speak(self):
        print("Cat meows.")

# Polymorphism in action
animals = [Dog(), Cat()]

for animal in animals:
    animal.speak()

Output:

Dog barks.
Cat meows.

In this case:

  • The Animal class is abstract and defines an abstract method speak().
  • Both Dog and Cat are concrete classes that implement the speak() method.
  • The speak() method is called polymorphically, with different implementations for each class.

6. Advantages of Polymorphism

  • Code Reusability: Polymorphism allows you to write more generic code, which can be reused with different types of objects.
  • Flexibility: It enables a single function or method to work with objects of different classes.
  • Maintainability: With polymorphism, you can add new types of objects without changing the existing code that uses polymorphic methods, promoting easy extension of your codebase.
  • Abstraction: It allows you to use abstract classes or interfaces, hiding the specific details of implementation while providing a common interface.

7. Summary

  • Polymorphism enables objects of different types to be treated as objects of a common superclass, allowing the same method or function call to behave differently based on the type of object.
  • It can be achieved through method overriding, duck typing, and operator overloading in Python.
  • Abstract classes and interfaces can also be used to achieve polymorphism by defining common interfaces that subclasses implement.
  • The primary benefit of polymorphism is its ability to simplify code, reduce redundancy, and promote flexibility and maintainability.

Polymorphism is an essential feature in OOP that helps in making code more modular and extensible, allowing different types of objects to interact in a consistent way.

Popular Posts