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:
class Superclass:
def method(self):
pass
class Subclass(Superclass):
def method(self):
pass
class Superclass:
def method(self):
pass
class Subclass(Superclass):
def method(self):
pass
In this example, the Subclass
Subclass
overrides the method
method
inherited from the Superclass
Superclass
by redefining it with the same name and parameters. The method
method
in the Subclass
Subclass
provides a specialized implementation that replaces the method
method
inherited from the Superclass
Superclass
.
Method Overriding Example:
Letβs look at an example of method overriding in Python:
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()
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:
Bark!
Meow!
Bark!
Meow!
In this example, we have a base class Animal
Animal
with a method make_sound
make_sound
. We have two subclasses Dog
Dog
and Cat
Cat
that override the make_sound
make_sound
method inherited from the Animal
Animal
class. The Dog
Dog
and Cat
Cat
classes provide specialized implementations of the make_sound
make_sound
method that are specific to each animal. The Dog
Dog
class overrides the make_sound
make_sound
method to print βBark!β, while the Cat
Cat
class overrides the make_sound
make_sound
method to print βMeow!β. When we call the make_sound
make_sound
method on the dog
dog
and cat
cat
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 Animal
Animal
class has a method make_sound
make_sound
. The Dog
Dog
and Cat
Cat
classes inherit from the Animal
Animal
class and override the make_sound
make_sound
method. The Dog
Dog
class overrides the make_sound
make_sound
method to print βBark!β, while the Cat
Cat
class overrides the make_sound
make_sound
method to print βMeow!β. When we call the make_sound
make_sound
method on the dog
dog
and cat
cat
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 Overriding | Method 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:
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()
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:
C:\Users\username>python method_overriding.py
John is coding.
Jane is designing.
C:\Users\username>python method_overriding.py
John is coding.
Jane is designing.
In this example, we have a base class Employee
Employee
with a method work
work
. We have two subclasses SoftwareEngineer
SoftwareEngineer
and Designer
Designer
that override the work
work
method inherited from the Employee
Employee
class. The SoftwareEngineer
SoftwareEngineer
and Designer
Designer
classes provide specialized implementations of the work
work
method that are specific to each employee. The SoftwareEngineer
SoftwareEngineer
class overrides the work
work
method to print βJohn is coding.β, while the Designer
Designer
class overrides the work
work
method to print βJane is designing.β. When we call the work
work
method on the software_engineer
software_engineer
and designer
designer
objects, the overridden methods in the respective subclasses are invoked, printing βJohn is coding.β and βJane is designing.β.
Another example of 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()
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:
C:\Users\username>python method_overriding.py
Hello, I am John. My roll number is 1.
Hello, I am Jane. I teach Math.
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 Person
Person
with a method greet
greet
. We have two subclasses Student
Student
and Teacher
Teacher
that override the greet
greet
method inherited from the Person
Person
class. The Student
Student
and Teacher
Teacher
classes provide specialized implementations of the greet
greet
method that are specific to each person. The Student
Student
class overrides the greet
greet
method to print βHello, I am John. My roll number is 1.β, while the Teacher
Teacher
class overrides the greet
greet
method to print βHello, I am Jane. I teach Math.β. When we call the greet
greet
method on the student
student
and teacher
teacher
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:
__init__
__init__
__str__
__str__
__repr__
__repr__
__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.
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)
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:
C:\Users\username>python base_overriding_methods.py
John
1
C:\Users\username>python base_overriding_methods.py
John
1
In this example, we have a base class Person
Person
with an __init__
__init__
method. We have a subclass Student
Student
that overrides the __init__
__init__
method inherited from the Person
Person
class. The Student
Student
class overrides the __init__
__init__
method to initialize the name
name
and roll_number
roll_number
attributes of the Student
Student
class. When we create a Student
Student
object, the __init__
__init__
method in the Student
Student
class is invoked, initializing the name
name
and roll_number
roll_number
attributes of the Student
Student
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.
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)
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:
C:\Users\username>python base_overriding_methods.py
Student: John 1
C:\Users\username>python base_overriding_methods.py
Student: John 1
In this example, we have a base class Person
Person
with a __str__
__str__
method. We have a subclass Student
Student
that overrides the __str__
__str__
method inherited from the Person
Person
class. The Student
Student
class overrides the __str__
__str__
method to return a string representation of the Student
Student
object. When we call the print()
print()
function on the student
student
object, the __str__
__str__
method in the Student
Student
class is invoked, returning a string representation of the Student
Student
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.
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))
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:
C:\Users\username>python base_overriding_methods.py
Student: John 1
C:\Users\username>python base_overriding_methods.py
Student: John 1
In this example, we have a base class Person
Person
with a __repr__
__repr__
method. We have a subclass Student
Student
that overrides the __repr__
__repr__
method inherited from the Person
Person
class. The Student
Student
class overrides the __repr__
__repr__
method to return a string representation of the Student
Student
object. When we call the repr()
repr()
function on the student
student
object, the __repr__
__repr__
method in the Student
Student
class is invoked, returning a string representation of the Student
Student
object.
4. __del__
__del__
:
The __del__
__del__
method is used to delete an object. It is called when an object is deleted using the del
del
keyword.
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
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:
C:\Users\username>python base_overriding_methods.py
Deleting John 1
C:\Users\username>python base_overriding_methods.py
Deleting John 1
In this example, we have a base class Person
Person
with a __del__
__del__
method. We have a subclass Student
Student
that overrides the __del__
__del__
method inherited from the Person
Person
class. The Student
Student
class overrides the __del__
__del__
method to print a message when the Student
Student
object is deleted. When we delete the student
student
object using the del
del
keyword, the __del__
__del__
method in the Student
Student
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.
class Dog(Animal):
def make_sound(self):
super().make_sound() # Calls the make_sound method of the superclass
print("Bark!")
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.
animals = [Dog(), Cat()]
for animal in animals:
animal.make_sound() # Outputs: Bark! Meow!
animals = [Dog(), Cat()]
for animal in animals:
animal.make_sound() # Outputs: Bark! Meow!
Output:
C:\Users\username>python method_overriding.py
Generic animal sound
Bark!
Generic animal sound
Meow!
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