Method Overriding
Replace a parent class’s method with your own implementation in a child class — the foundation of polymorphism.
"Overriding is a child class saying: 'I inherited your method, but I know better how to do this for my specific case.'"
— ShurAIWhat is Method Overriding?
When a child class defines a method with the same name as a method in the parent class, the child’s version replaces the parent’s version for that class. This is called overriding:
class Animal:
def speak(self):
print("Some animal sound")
class Dog(Animal):
def speak(self): # overrides Animal.speak
print("Woof!")
class Cat(Animal):
def speak(self): # overrides Animal.speak differently
print("Meow!")
Animal().speak() # Some animal sound
Dog().speak() # Woof!
Cat().speak() # Meow!
Polymorphism — One Interface, Many Behaviours
Because all three classes have a speak() method, you can call it on any of them through a shared loop — each responds in its own way. This is called polymorphism:
animals = [Dog(), Cat(), Dog(), Cat()]
for animal in animals:
animal.speak() # each object uses its own version
# Woof!
# Meow!
# Woof!
# Meow!
d = Dog() d.speak() # "Some animal sound" # (uses parent's version)
d = Dog() d.speak() # "Woof!" # (uses Dog's version)
Extending the Parent Method
Use super().method() to run the parent version plus add your own logic:
class Shape:
def describe(self):
print("I am a shape.")
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def describe(self):
super().describe() # run parent first
print(f"I am a circle with radius {self.radius}.")
Circle(5).describe()
# I am a shape.
# I am a circle with radius 5.
Real Example — Notification System
class Notification:
def __init__(self, message):
self.message = message
def send(self):
print(f"[Notification] {self.message}")
class EmailNotification(Notification):
def __init__(self, message, to):
super().__init__(message)
self.to = to
def send(self): # overrides send()
print(f"[Email to {self.to}] {self.message}")
class SMSNotification(Notification):
def __init__(self, message, phone):
super().__init__(message)
self.phone = phone
def send(self): # overrides send() differently
print(f"[SMS to {self.phone}] {self.message}")
alerts = [
EmailNotification("Your order shipped!", "riya@mail.com"),
SMSNotification("OTP: 4821", "+91 98765"),
Notification("System maintenance at 2AM"),
]
for alert in alerts:
alert.send()
[Email to riya@mail.com] Your order shipped!
[SMS to +91 98765] OTP: 4821
[Notification] System maintenance at 2AM
"Polymorphism is what makes overriding powerful. Write for item in items: item.process() and each item does the right thing automatically, no matter what type it is."
🧠 Quiz — Q1
What is method overriding?
🧠 Quiz — Q2
You have Dog inheriting from Animal. Both have a speak() method. When you call dog.speak(), which runs?
🧠 Quiz — Q3
What is polymorphism?
🧠 Quiz — Q4
You override describe() in a child but also want to run the parent's describe(). How?