Skip to content

Method Overriding in Python

Method Overriding in Python: Redefining Behavior with Elegance

Method overriding is a fundamental concept in object-oriented programming (OOP) that allows a subclass to provide a specific implementation of a method that is already defined in its superclass. This process enables the subclass to tailor the behavior of the inherited method to suit its own requirements. In Python, method overriding contributes to the flexibility and extensibility of code, promoting a clean and elegant approach to designing and extending classes.

The Basics of Method Overriding:

Inheritance in Python allows a subclass to inherit attributes and methods from its superclass. Method overriding occurs when a method in the subclass has the same name and parameters as a method in its superclass. The overridden method in the subclass provides a specialized implementation, effectively replacing the method inherited from the superclass.

Method Overriding Syntax:

The syntax for method overriding in Python is as follows:

method_overriding.py
class Superclass:
    def method(self):
        pass
 
class Subclass(Superclass):
    def method(self):
        pass
method_overriding.py
class Superclass:
    def method(self):
        pass
 
class Subclass(Superclass):
    def method(self):
        pass

In this example, the SubclassSubclass overrides the methodmethod inherited from the SuperclassSuperclass by redefining it with the same name and parameters. The methodmethod in the SubclassSubclass provides a specialized implementation that replaces the methodmethod inherited from the SuperclassSuperclass.

Method Overriding Example:

Let’s look at an example of method overriding in Python:

method_overriding.py
class Animal:
    def make_sound(self):
        print("Generic animal sound")
 
class Dog(Animal):
    def make_sound(self):
        print("Bark!")
 
class Cat(Animal):
    def make_sound(self):
        print("Meow!")
 
dog = Dog()
cat = Cat()
dog.make_sound()
cat.make_sound()
method_overriding.py
class Animal:
    def make_sound(self):
        print("Generic animal sound")
 
class Dog(Animal):
    def make_sound(self):
        print("Bark!")
 
class Cat(Animal):
    def make_sound(self):
        print("Meow!")
 
dog = Dog()
cat = Cat()
dog.make_sound()
cat.make_sound()

Output:

command
Bark!
Meow!
command
Bark!
Meow!

In this example, we have a base class AnimalAnimal with a method make_soundmake_sound. We have two subclasses DogDog and CatCat that override the make_soundmake_sound method inherited from the AnimalAnimal class. The DogDog and CatCat classes provide specialized implementations of the make_soundmake_sound method that are specific to each animal. The DogDog class overrides the make_soundmake_sound method to print β€œBark!”, while the CatCat class overrides the make_soundmake_sound method to print β€œMeow!β€œ. When we call the make_soundmake_sound method on the dogdog and catcat objects, the overridden methods in the respective subclasses are invoked, printing β€œBark!” and β€œMeow!β€œ.

Diagrammatic Representation of Method Overriding:

The following diagram illustrates the concept of method overriding in Python:

Method Overriding


  classDiagram
    class Animal {
        + make_sound()
    }
    class Dog {
        + make_sound()
    }
    class Cat {
        + make_sound()
    }
    Animal <|-- Dog
    Animal <|-- Cat

Method Overriding

In this example, the AnimalAnimal class has a method make_soundmake_sound. The DogDog and CatCat classes inherit from the AnimalAnimal class and override the make_soundmake_sound method. The DogDog class overrides the make_soundmake_sound method to print β€œBark!”, while the CatCat class overrides the make_soundmake_sound method to print β€œMeow!β€œ. When we call the make_soundmake_sound method on the dogdog and catcat objects, the overridden methods in the respective subclasses are invoked, printing β€œBark!” and β€œMeow!β€œ.

Method Overriding vs. Method Overloading

Method overriding is often confused with method overloading. However, they are two different concepts. Method overloading is the ability to define multiple methods with the same name but with different parameters. Method overriding is the ability of a subclass to change the implementation of a method provided by one of its ancestors. Overriding is a very important part of OOP since it is the feature that makes inheritance exploit its full power.

Method OverridingMethod Overloading
Method overriding is the ability of a subclass to change the implementation of a method provided by one of its ancestors.Method overloading is the ability to define multiple methods with the same name but with different parameters.
Method overriding is a very important part of OOP since it is the feature that makes inheritance exploit its full power.Method overloading is not a very important part of OOP.
Method overriding is achieved by redefining a method in the subclass with the same name and parameters as a method in its superclass.Method overloading is achieved by defining multiple methods with the same name but with different parameters.
Method overriding is also known as runtime polymorphism.Method overloading is also known as compile-time polymorphism.
Method overriding is a feature of inheritance.Method overloading is not a feature of inheritance.
Method overriding is a key element of polymorphism in OOP.Method overloading is not a key element of polymorphism in OOP.

More examples of Method Overriding:

Let’s look at an example of method overriding in Python:

method_overriding.py
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
 
    def work(self):
        print(self.name + " is working.")
 
class SoftwareEngineer(Employee):
    def __init__(self, name, salary, level):
        super().__init__(name, salary)
        self.level = level
 
    def work(self):
        print(self.name + " is coding.")
 
    def debug(self):
        print(self.name + " is debugging.")
 
class Designer(Employee):
    def work(self):
        print(self.name + " is designing.")
 
    def draw(self):
        print(self.name + " is drawing.")
 
software_engineer = SoftwareEngineer("John", 1000, "Junior")
designer = Designer("Jane", 1000)
employees = [software_engineer, designer]
 
for employee in employees:
    employee.work()
method_overriding.py
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
 
    def work(self):
        print(self.name + " is working.")
 
class SoftwareEngineer(Employee):
    def __init__(self, name, salary, level):
        super().__init__(name, salary)
        self.level = level
 
    def work(self):
        print(self.name + " is coding.")
 
    def debug(self):
        print(self.name + " is debugging.")
 
class Designer(Employee):
    def work(self):
        print(self.name + " is designing.")
 
    def draw(self):
        print(self.name + " is drawing.")
 
software_engineer = SoftwareEngineer("John", 1000, "Junior")
designer = Designer("Jane", 1000)
employees = [software_engineer, designer]
 
for employee in employees:
    employee.work()

Output:

command
C:\Users\username>python method_overriding.py
John is coding.
Jane is designing.
command
C:\Users\username>python method_overriding.py
John is coding.
Jane is designing.

In this example, we have a base class EmployeeEmployee with a method workwork. We have two subclasses SoftwareEngineerSoftwareEngineer and DesignerDesigner that override the workwork method inherited from the EmployeeEmployee class. The SoftwareEngineerSoftwareEngineer and DesignerDesigner classes provide specialized implementations of the workwork method that are specific to each employee. The SoftwareEngineerSoftwareEngineer class overrides the workwork method to print β€œJohn is coding.”, while the DesignerDesigner class overrides the workwork method to print β€œJane is designing.”. When we call the workwork method on the software_engineersoftware_engineer and designerdesigner objects, the overridden methods in the respective subclasses are invoked, printing β€œJohn is coding.” and β€œJane is designing.”.

Another example of method overriding:

method_overriding
class Person:
    def __init__(self, name):
        self.name = name
 
    def greet(self):
        print("Hello, I am " + self.name + ".")
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
 
    def greet(self):
        print("Hello, I am " + self.name + ". My roll number is " + str(self.roll_number) + ".")
 
class Teacher(Person):
    def __init__(self, name, subject):
        super().__init__(name)
        self.subject = subject
 
    def greet(self):
        print("Hello, I am " + self.name + ". I teach " + self.subject + ".")
 
student = Student("John", 1)
teacher = Teacher("Jane", "Math")
people = [student, teacher]
 
for person in people:
    person.greet()
method_overriding
class Person:
    def __init__(self, name):
        self.name = name
 
    def greet(self):
        print("Hello, I am " + self.name + ".")
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
 
    def greet(self):
        print("Hello, I am " + self.name + ". My roll number is " + str(self.roll_number) + ".")
 
class Teacher(Person):
    def __init__(self, name, subject):
        super().__init__(name)
        self.subject = subject
 
    def greet(self):
        print("Hello, I am " + self.name + ". I teach " + self.subject + ".")
 
student = Student("John", 1)
teacher = Teacher("Jane", "Math")
people = [student, teacher]
 
for person in people:
    person.greet()

Output:

command
C:\Users\username>python method_overriding.py
Hello, I am John. My roll number is 1.
Hello, I am Jane. I teach Math.
command
C:\Users\username>python method_overriding.py
Hello, I am John. My roll number is 1.
Hello, I am Jane. I teach Math.

In this example, we have a base class PersonPerson with a method greetgreet. We have two subclasses StudentStudent and TeacherTeacher that override the greetgreet method inherited from the PersonPerson class. The StudentStudent and TeacherTeacher classes provide specialized implementations of the greetgreet method that are specific to each person. The StudentStudent class overrides the greetgreet method to print β€œHello, I am John. My roll number is 1.”, while the TeacherTeacher class overrides the greetgreet method to print β€œHello, I am Jane. I teach Math.”. When we call the greetgreet method on the studentstudent and teacherteacher objects, the overridden methods in the respective subclasses are invoked, printing β€œHello, I am John. My roll number is 1.” and β€œHello, I am Jane. I teach Math.”.

Base Overriding Methods:

In Python, there are several methods that are commonly overridden in subclasses. These methods are known as base overriding methods. Let’s look at some of the base overriding methods in Python:

  1. __init____init__
  2. __str____str__
  3. __repr____repr__
  4. __del____del__

1. __init____init__:

The __init____init__ method is used to initialize an object. It is called when an object is created from a class and allows the class to initialize the attributes of the class.

base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
student = Student("John", 1)
print(student.name)
print(student.roll_number)
base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
student = Student("John", 1)
print(student.name)
print(student.roll_number)

Output:

command
C:\Users\username>python base_overriding_methods.py
John
1
command
C:\Users\username>python base_overriding_methods.py
John
1

In this example, we have a base class PersonPerson with an __init____init__ method. We have a subclass StudentStudent that overrides the __init____init__ method inherited from the PersonPerson class. The StudentStudent class overrides the __init____init__ method to initialize the namename and roll_numberroll_number attributes of the StudentStudent class. When we create a StudentStudent object, the __init____init__ method in the StudentStudent class is invoked, initializing the namename and roll_numberroll_number attributes of the StudentStudent object.

2. __str____str__:

The __str____str__ method is used to return a string representation of an object. It is called when the print()print() or str()str() function is invoked on an object.

base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return "Person: " + self.name
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __str__(self):
        return "Student: " + self.name + " " + str(self.roll_number)
 
student = Student("John", 1)
print(student)
base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return "Person: " + self.name
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __str__(self):
        return "Student: " + self.name + " " + str(self.roll_number)
 
student = Student("John", 1)
print(student)

Output:

command
C:\Users\username>python base_overriding_methods.py
Student: John 1
command
C:\Users\username>python base_overriding_methods.py
Student: John 1

In this example, we have a base class PersonPerson with a __str____str__ method. We have a subclass StudentStudent that overrides the __str____str__ method inherited from the PersonPerson class. The StudentStudent class overrides the __str____str__ method to return a string representation of the StudentStudent object. When we call the print()print() function on the studentstudent object, the __str____str__ method in the StudentStudent class is invoked, returning a string representation of the StudentStudent object.

3. __repr____repr__:

The __repr____repr__ method is used to return a string representation of an object. It is called when the repr()repr() function is invoked on an object.

base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return "Person: " + self.name
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __repr__(self):
        return "Student: " + self.name + " " + str(self.roll_number)
 
student = Student("John", 1)
print(repr(student))
base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return "Person: " + self.name
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __repr__(self):
        return "Student: " + self.name + " " + str(self.roll_number)
 
student = Student("John", 1)
print(repr(student))

Output:

command
C:\Users\username>python base_overriding_methods.py
Student: John 1
command
C:\Users\username>python base_overriding_methods.py
Student: John 1

In this example, we have a base class PersonPerson with a __repr____repr__ method. We have a subclass StudentStudent that overrides the __repr____repr__ method inherited from the PersonPerson class. The StudentStudent class overrides the __repr____repr__ method to return a string representation of the StudentStudent object. When we call the repr()repr() function on the studentstudent object, the __repr____repr__ method in the StudentStudent class is invoked, returning a string representation of the StudentStudent object.

4. __del____del__:

The __del____del__ method is used to delete an object. It is called when an object is deleted using the deldel keyword.

base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print("Deleting " + self.name)
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __del__(self):
        print("Deleting " + self.name + " " + str(self.roll_number))
 
student = Student("John", 1)
del student
base_overriding_methods.py
class Person:
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print("Deleting " + self.name)
 
class Student(Person):
    def __init__(self, name, roll_number):
        super().__init__(name)
        self.roll_number = roll_number
    def __del__(self):
        print("Deleting " + self.name + " " + str(self.roll_number))
 
student = Student("John", 1)
del student

Output:

command
C:\Users\username>python base_overriding_methods.py
Deleting John 1
command
C:\Users\username>python base_overriding_methods.py
Deleting John 1

In this example, we have a base class PersonPerson with a __del____del__ method. We have a subclass StudentStudent that overrides the __del____del__ method inherited from the PersonPerson class. The StudentStudent class overrides the __del____del__ method to print a message when the StudentStudent object is deleted. When we delete the studentstudent object using the deldel keyword, the __del____del__ method in the StudentStudent class is invoked, printing a message.

Key Features and Considerations:

1. Method Signature:

  • The overriding method in the subclass must have the same method signature (name and parameters) as the method in the superclass.

2. Dynamic Binding:

  • Method overriding in Python involves dynamic binding, where the decision about which method to call is made at runtime based on the type of the object.

3. Access to Superclass Method:

  • Inside the overridden method, you can access the method of the superclass using the super()super() function.
method_overriding.py
class Dog(Animal):
    def make_sound(self):
        super().make_sound()  # Calls the make_sound method of the superclass
        print("Bark!")
method_overriding.py
class Dog(Animal):
    def make_sound(self):
        super().make_sound()  # Calls the make_sound method of the superclass
        print("Bark!")

4. Polymorphism:

  • Method overriding is a key element of polymorphism in OOP. It allows objects of different classes to be treated uniformly based on a common interface.
method_overrinding.py
animals = [Dog(), Cat()]
for animal in animals:
    animal.make_sound()  # Outputs: Bark!  Meow!
method_overrinding.py
animals = [Dog(), Cat()]
for animal in animals:
    animal.make_sound()  # Outputs: Bark!  Meow!

Output:

command
C:\Users\username>python method_overriding.py
Generic animal sound
Bark!
Generic animal sound
Meow!
command
C:\Users\username>python method_overriding.py
Generic animal sound
Bark!
Generic animal sound
Meow!

5. Consistency Across the Hierarchy:

  • In a class hierarchy, if a method is overridden in a subclass, it should be consistently overridden in all its subclasses. This ensures a predictable and maintainable codebase.

Use Cases and Best Practices:

1. Customizing Behavior:

  • Method overriding is useful when you want to customize the behavior of a method inherited from a superclass to better suit the needs of a subclass.

2. Extending Functionality:

  • Subclasses can override methods to extend or enhance the functionality provided by the superclass.

3. Maintaining a Common Interface:

  • Method overriding contributes to maintaining a common interface across related classes, facilitating polymorphism.

4. Design Patterns:

  • Method overriding is often employed in design patterns like the Template Method Pattern, where a superclass provides a template method that is overridden by its subclasses.

Conclusion:

Method overriding in Python is a powerful mechanism for tailoring the behavior of a subclass by redefining methods inherited from its superclass. It promotes code reuse, flexibility, and consistency across class hierarchies. Understanding and leveraging method overriding is essential for creating well-structured and extensible object-oriented code in Python. For more information on method overriding, refer to the official documentation. For more tutorials on object-oriented programming in Python, refer to the official documentation. For more tutorial, visit Python Central Hub.

Was this page helpful?

Let us know how we did