Inheritance and Polymorphism are two of the four primary pillars of OOP. They allow developers to create a new class based on an existing class (Inheritance) and use them in an interchangeable way (Polymorphism), enhancing code reusability and flexibility.
Inheritance enables a new class to inherit attributes and behaviors (methods) from an existing class.
The class whose properties and methods are inherited by another class.
The class that inherits properties and methods from another class.
Example:
# Base Class
class Animal:
def __init__(self, species):
self.species = species
def speak(self):
pass
# Derived Class
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
In the example, Dog
and Cat
are derived from the Animal
class.
super()
FunctionIt’s often needed to call a method in the parent class from inside the child class, especially when overriding methods. The super()
function helps with this.
class Bird(Animal):
def __init__(self, species, can_fly):
super().__init__(species)
self.can_fly = can_fly
Polymorphism, from Greek, means “many shapes”. It refers to the ability of different classes to be treated as instances of the same class through inheritance. The classic example is having a method with the same name in both parent and child classes, but the child’s method overrides or extends the parent’s method.
Example using the above classes:
def animal_sound(animal):
print(animal.speak())
dog = Dog("Golden Retriever")
cat = Cat("Persian")
animal_sound(dog) # Outputs: Woof!
animal_sound(cat) # Outputs: Meow!
In this scenario, despite the animal_sound
function designed to accept an Animal
type object, due to polymorphism, it can handle any object of derived types (Dog
, Cat
, etc.) as well.
Overriding: A derived class has a definition for one of the parent class’s methods that it intends to provide a different implementation for.
Overloading: Python doesn’t support method overloading like other languages where you can have multiple methods with the same name but different parameters. However, default parameters and variable-length argument lists (using *args and **kwargs) offer a similar solution.
Python’s approach to polymorphism is a bit different from strongly typed languages. It employs a concept called “Duck Typing”, which stems from the saying, “If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.”
This means that the type or class of an object is determined by its behavior (methods and properties) rather than its class inheritance.
Example:
class Duck:
def quack(self):
return "Quack!"
class Robot:
def quack(self):
return "Beep quack!"
def duck_sound(creature):
return creature.quack()
duck = Duck()
robot = Robot()
print(duck_sound(duck)) # Outputs: Quack!
print(duck_sound(robot)) # Outputs: Beep quack!
Although Robot
doesn’t inherit from Duck
, it’s still treated as a “duck” in the duck_sound
function due to its quack
method.
Inheritance and polymorphism are powerful tools in object-oriented programming, enabling developers to write more organized, efficient, and reusable code. By leveraging these concepts, one can model complex systems using simple, maintainable, and extensible code structures.