Polymorphism is one of the core principles of object-oriented programming (OOP) that allows objects of different classes to be treated as objects of a common superclass. It provides a way to perform a single action in different forms. Essentially, polymorphism enables a single function, method, or operator to work in different ways depending on the context.
1. Method Overriding (Runtime Polymorphism)
2. Method Overloading (Compile-time Polymorphism)
3. Operator Overloading
Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. This allows the subclass to modify or extend the behavior of the superclass method.
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
print("Dog barks")
class Cat(Animal):
def speak(self):
print("Cat meows")
# Usage
def make_animal_speak(animal):
animal.speak()
# Creating instances
dog = Dog()
cat = Cat()
make_animal_speak(dog) # Output: Dog barks
make_animal_speak(cat) # Output: Cat meows
In this example:
The speak method is overridden in both Dog and Cat classes.
The make_animal_speak function can work with any object of the Animal type, demonstrating runtime polymorphism.
Method overloading refers to defining multiple methods with the same name but different signatures (number or type of parameters). However, Python does not support method overloading in the traditional sense like some other languages (e.g., C++ or Java). Instead, Python uses default arguments or variable-length arguments to achieve similar functionality.
class Printer:
def print_message(self, message, times=1):
for _ in range(times):
print(message)
# Usage
printer = Printer()
printer.print_message("Hello") # Output: Hello
printer.print_message("Hello", 3) # Output: Hello (repeated 3 times)
Operator overloading allows defining how operators behave for user-defined classes. By implementing special methods (often referred to as magic methods), you can customize the behavior of operators like +, -, *, etc.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y +
other.y)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
# Usage
v1 = Vector(1, 2)
v2 = Vector(3, 4)
result = v1 + v2
print(result) # Output: Vector(4, 6)
In this example:
• The __add__ method is overridden to define how the + operator works with Vector objects.
1. Flexibility: Functions and methods can handle a wide variety of object types, making your code more flexible and easier to extend.
2. Code Reusability: Common interfaces can be used to work with different types of objects, reducing code duplication.
3. Maintainability: Code that relies on polymorphism is easier to maintain and modify, as changes to the implementation do not affect the interface.
Polymorphism enhances the ability of objects to interact with each other in a flexible and dynamic way, making it a powerful concept in Python and OOP in general.