Polymorphism Example in Java and Python

In Java, you achieve dynamic polymorphism by overriding a method in a subclass and then referring to subclass objects via a parent class reference. The actual method that gets executed is determined at runtime based on the object type.

// Base class
class Animal {
    public void sound() {
        System.out.println("Animal makes a generic sound");
    }
}

// Subclass Dog overriding the sound() method
class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

// Subclass Cat overriding the sound() method
class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Cat meows");
    }
}

// Main class to test dynamic polymorphism
public class DynamicPolymorphismDemo {
    public static void main(String[] args) {
        // Parent class reference pointing to a Dog instance
        Animal animal = new Dog();
        animal.sound(); // Output: Dog barks

        // Parent class reference now pointing to a Cat instance
        animal = new Cat();
        animal.sound(); // Output: Cat meows
    }
}

Explanation:

  1. Method Overriding: Both Dog and Cat override the sound() method in the Animal class.

  2. Dynamic Binding at Runtime: The reference variable animal is declared as type Animal, but when assigned a Dog object and later a Cat object, the correct overridden method gets called based on the actual object's type.

  3. Flexibility: This allows for extending to more classes later, each with its own version of the sound() method, making the code more flexible and scalable.

 

Dynamic Polymorphism in Python

Python uses a similar approach. Due to its dynamic nature, method overriding in subclasses automatically ensures that the correct method is called based on the instance at runtime.

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

class Dog(Animal):
    def sound(self):
        print("Dog barks")

class Cat(Animal):
    def sound(self):
        print("Cat meows")

def main():
    # List of different Animal objects
    animals = [Dog(), Cat()]
    
    # The correct sound() method is called for each object
    for animal in animals:
        animal.sound()

if __name__ == '__main__':
    main()
 

Explanation:

  1. Method Overriding: Both Dog and Cat classes override the sound() method defined in the base class Animal.

  2. Dynamic Dispatch: By iterating over a list of Animal instances (which are actually Dog and Cat objects), Python dynamically decides which sound() method to invoke based on the object's actual type.

  3. Simple and Flexible: This pattern lets you add new subclasses with their own behaviors without modifying the parts of your code that use the base class.

 

Both examples illustrate dynamic polymorphism where the decision over which method to run is deferred until the program is running. This concept is crucial in object-oriented programming, allowing developers to write code that is flexible, scalable, and easier to maintain.