How is polymorphism achieved at compile time and run time? Explain with the help of suitable example.


Q.) How is polymorphism achieved at compile time and run time? Explain with the help of suitable example.

Subject: Object Oriented Programming and Methodology

Polymorphism is a key feature of object-oriented programming that allows objects of different subclasses to respond to the same method call in a unique way. This enables a higher level of flexibility and code reusability in object-oriented design. Polymorphism can be achieved at compile time and run time:

Compile-Time Polymorphism (Static Binding):

Compile-time polymorphism, also known as static binding, is performed by the compiler during the compilation phase of a program. It involves method overloading and function overloading, where multiple methods or functions with the same name are defined in a class or module but with different argument types or numbers. The compiler determines which method or function to call based on the actual arguments passed during the method or function call.

Example:

class Shape:
    def area(self):
        raise NotImplementedError

class Square:
    def __init__(self, side):
        self.side = side

    def area(self):
        return self.side ** 2

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

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

def calculate_total_area(shapes):
    total_area = 0
    for shape in shapes:
        total_area += shape.area()
    return total_area

# Create a list of shapes
shapes = [Square(5), Circle(3), Square(7)]

# Calculate the total area using compile-time polymorphism
total_area = calculate_total_area(shapes)

print("Total area:", total_area)

In this example, the Shape class defines a method called area, which can calculate the area of different shapes. The Square and Circle classes inherit from Shape and provide their own implementations of the area method. The calculate_total_area function takes a list of Shape objects and calculates the total area by calling the area method on each shape. Since the area method is overloaded in the subclasses, the compiler determines which implementation to call based on the type of the object at compile time.

Run-Time Polymorphism (Dynamic Binding):

Run-time polymorphism, also known as dynamic binding, occurs during the execution of a program. It involves method overriding, where a subclass provides a new implementation of a method inherited from its parent class. When a method is called on an object, the actual method to be executed is determined at run time based on the object's class.

Example:

class Animal:
    def make_sound(self):
        print("Animal makes a sound.")

class Dog(Animal):
    def make_sound(self):
        print("Dog barks.")

class Cat(Animal):
    def make_sound(self):
        print("Cat meows.")

def make_animal_sound(animal):
    animal.make_sound()

# Create instances of Animal, Dog, and Cat
animal = Animal()
dog = Dog()
cat = Cat()

# Call the make_sound method using run-time polymorphism
make_animal_sound(animal)
make_animal_sound(dog)
make_animal_sound(cat)

In this example, the Animal class defines a method called make_sound. The Dog and Cat classes inherit from Animal and provide their own implementations of the make_sound method. The make_animal_sound function takes an Animal object and calls the make_sound method on it. Since the make_sound method is overridden in the subclasses, the actual method to be executed is determined at run time based on the object's class.

In summary, compile-time polymorphism is achieved through method and function overloading, where the compiler determines which method or function to call based on the argument types or numbers. Run-time polymorphism is achieved through method overriding, where the actual method to be executed is determined at run time based on the object's class. Both compile-time and run-time polymorphism contribute to the flexibility and extensibility of object-oriented programming.