Skip to main content

Python Method Overriding

Method overriding is a core concept in object-oriented programming that allows a subclass (child class) to provide a specific implementation of a method that already exists in its parent class. This powerful feature enables you to customize or extend the behavior of inherited methods to suit the specific requirements of the derived class.

What is Method Overriding?

Method overriding occurs when a child class defines a method with:

  • The same name
  • The same parameters
  • The same return type

as a method already defined in its parent class. When an overridden method is called on an object of the child class, the child's version of the method executes instead of the parent's version.

Why Use Method Overriding?

Method overriding serves several important purposes:

  1. Customizing behavior: Adapting inherited methods to fit specific requirements
  2. Implementing polymorphism: Allowing different classes to respond differently to the same method call
  3. Extending functionality: Building upon existing functionality while adding new features

Basic Method Overriding in Python

Let's look at a simple example to understand how method overriding works:

python
class Animal:
def make_sound(self):
print("Some generic animal sound")

class Dog(Animal):
def make_sound(self): # This overrides the make_sound method in the Animal class
print("Woof!")

class Cat(Animal):
def make_sound(self): # This also overrides the make_sound method in the Animal class
print("Meow!")

# Create instances
generic_animal = Animal()
dog = Dog()
cat = Cat()

# Call the make_sound method on each instance
generic_animal.make_sound() # Output: Some generic animal sound
dog.make_sound() # Output: Woof!
cat.make_sound() # Output: Meow!

In this example:

  • The Animal class has a make_sound() method
  • Both Dog and Cat classes inherit from Animal
  • Both child classes override the make_sound() method with their specific implementations
  • When make_sound() is called on each object, the appropriate version executes

Accessing the Parent Class Method

Sometimes, you may want to extend the functionality of a parent class method rather than completely replace it. Python's super() function allows you to call the parent class's method from within the overriding method:

python
class Vehicle:
def describe(self):
return "This is a vehicle"

class Car(Vehicle):
def describe(self):
# Call the parent class method first
base_description = super().describe()
# Extend with additional information
return f"{base_description} with four wheels"

# Create instances
vehicle = Vehicle()
car = Car()

# Call the describe method on each instance
print(vehicle.describe()) # Output: This is a vehicle
print(car.describe()) # Output: This is a vehicle with four wheels

In this example, the Car class doesn't completely replace the describe() method but extends it using super().describe() to call the parent class's version before adding its own functionality.

Method Overriding vs. Method Overloading

It's important to distinguish between method overriding and method overloading:

  • Method overriding: Providing a new implementation for an inherited method (same method signature)
  • Method overloading: Defining multiple methods with the same name but different parameters

While Python doesn't support true method overloading through function signatures (as languages like Java do), you can simulate it using default parameters or variable argument lists.

Real-World Example: Shape Calculations

Let's look at a practical example involving geometric shapes:

python
import math

class Shape:
def area(self):
"""Calculate the area of the shape"""
raise NotImplementedError("Subclasses must implement this method")

def describe(self):
return "This is a generic shape"

class Circle(Shape):
def __init__(self, radius):
self.radius = radius

def area(self):
return math.pi * (self.radius ** 2)

def describe(self):
return f"This is a circle with radius {self.radius}"

class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

def describe(self):
return f"This is a rectangle with width {self.width} and height {self.height}"

# Create instances
circle = Circle(5)
rectangle = Rectangle(4, 6)

# Calculate and display area
print(circle.describe()) # Output: This is a circle with radius 5
print(f"Area: {circle.area():.2f}") # Output: Area: 78.54

print(rectangle.describe()) # Output: This is a rectangle with width 4 and height 6
print(f"Area: {rectangle.area()}") # Output: Area: 24

In this example:

  • The Shape base class defines the interface with area() and describe() methods
  • Circle and Rectangle classes override these methods with specific implementations
  • Each class provides its own logic for calculating area and describing itself

Method Overriding and Constructors

You can also override the __init__ constructor method. This is common when child classes need to initialize additional attributes:

python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def introduce(self):
return f"Hi, I'm {self.name} and I'm {self.age} years old."

class Student(Person):
def __init__(self, name, age, student_id):
# Call parent constructor
super().__init__(name, age)
# Add student-specific attribute
self.student_id = student_id

def introduce(self):
base_intro = super().introduce()
return f"{base_intro} My student ID is {self.student_id}."

# Create instances
person = Person("John", 30)
student = Student("Alice", 20, "A12345")

# Call the introduce method
print(person.introduce()) # Output: Hi, I'm John and I'm 30 years old.
print(student.introduce()) # Output: Hi, I'm Alice and I'm 20 years old. My student ID is A12345.

Note how the Student class:

  1. Overrides __init__ to accept an additional parameter
  2. Uses super().__init__(name, age) to call the parent constructor
  3. Adds its own attribute
  4. Extends the introduce() method using super()

Best Practices for Method Overriding

To effectively use method overriding in Python:

  1. Maintain the same interface: Keep the method signature consistent with the parent class
  2. Use super() when appropriate: Call the parent method when you want to extend rather than replace functionality
  3. Document any changes: Clearly document how your overridden method differs from the parent version
  4. Respect the Liskov Substitution Principle: Ensure that objects of the subclass can replace objects of the parent class without breaking the program

Method Overriding and Abstract Base Classes

Python's abc module provides Abstract Base Classes that can define methods that must be implemented by subclasses:

python
from abc import ABC, abstractmethod

class PaymentProcessor(ABC):
@abstractmethod
def process_payment(self, amount):
"""Process a payment of the given amount"""
pass

class CreditCardProcessor(PaymentProcessor):
def process_payment(self, amount):
print(f"Processing credit card payment of ${amount}")
# Credit card processing logic here

class PayPalProcessor(PaymentProcessor):
def process_payment(self, amount):
print(f"Processing PayPal payment of ${amount}")
# PayPal processing logic here

# These would work
cc_processor = CreditCardProcessor()
pp_processor = PayPalProcessor()

cc_processor.process_payment(100) # Output: Processing credit card payment of $100
pp_processor.process_payment(50) # Output: Processing PayPal payment of $50

# This would raise an error
# abstract_processor = PaymentProcessor() # TypeError: Can't instantiate abstract class

Abstract base classes provide a blueprint for derived classes, ensuring they implement required methods. This is a powerful way to enforce a consistent interface across related classes.

Summary

Method overriding is a fundamental concept in object-oriented programming that allows subclasses to modify or extend the behavior of methods inherited from parent classes. Key points to remember:

  • Method overriding occurs when a child class redefines a method from its parent class
  • The overriding method must have the same name and parameter list as the parent method
  • Use super() to access the parent class's version of an overridden method
  • Method overriding is essential for implementing polymorphism
  • Overriding enables customization of behavior while maintaining a consistent interface

By mastering method overriding, you can create more flexible and maintainable object-oriented code in Python.

Exercises

  1. Create a Vehicle class with a fuel_efficiency() method, then create ElectricVehicle and GasolineVehicle subclasses that override this method with appropriate implementations.

  2. Implement a BankAccount class with deposit() and withdraw() methods. Then create a SavingsAccount subclass that overrides these methods to enforce a minimum balance requirement.

  3. Extend the shape example from this lesson by adding a Triangle class that correctly calculates its area.

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)