Polymorphism - thehighestbidder/2143--Object-Oriented-Programming GitHub Wiki

Polymorphism

Definition:

Polymorphism, which literally means "many forms," is a fundamental principle of Object-Oriented Programming (OOP) that allows objects of different classes to respond to the same method call in their own specific way. It enables you to write code that can work with objects of various classes through a common interface, without needing to know the exact type of each object at compile time.

In essence, polymorphism allows you to treat objects of different classes uniformly if they share a common base class or interface. The specific behavior executed when a method is called depends on the actual type of the object at runtime.

Explanation:

Polymorphism is a powerful concept that contributes to flexibility, extensibility, and maintainability in OOP. It allows you to:

  • Write More Generic Code: You can write functions or methods that can operate on objects of different classes as long as they adhere to a common interface (e.g., inheriting from the same base class or implementing the same interface).
  • Increase Flexibility and Extensibility: New classes can be easily added to the system without requiring modifications to existing code that interacts with them through their common interface.
  • Improve Code Reusability: Polymorphic behavior often relies on inheritance or interfaces, which themselves promote code reuse.

Polymorphism is primarily achieved through two mechanisms:

  • Method Overriding: This occurs when a subclass provides its own specific implementation for a method that it has inherited from its superclass. The same method name can have different behaviors depending on the object's class.
  • Method Overloading (Note: Availability varies by language): This involves defining multiple methods within the same class that have the same name but different parameters (in terms of number, types, or order). The correct method to call is determined by the arguments passed during the method invocation. While often discussed under polymorphism, some languages treat it as a separate concept.

Analogy:

Consider different types of vehicles like cars, motorcycles, and bicycles. They all have a common action: "move." However, the way each vehicle "moves" is different: a car uses an engine, a motorcycle uses an engine and two wheels, and a bicycle uses pedals. The concept of "move" is polymorphic – the same instruction results in different behaviors based on the specific type of vehicle.

Code Examples (Python - demonstrating Method Overriding):

# Base class: Shape
class Shape:
    def area(self):
        print("Area of a generic shape")

    def display_area(self):
        self.area()

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

    # Override the area method for Rectangle
    def area(self):
        print(f"Area of the rectangle: {self.width * self.height}")

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

    # Override the area method for Circle
    def area(self):
        import math
        print(f"Area of the circle: {math.pi * self.radius**2:.2f}")

# Function that works with any Shape object (polymorphism in action)
def print_shape_area(shape):
    shape.display_area() # Calls the display_area method of the specific Shape object

# Creating objects of different Shape subclasses
rect = Rectangle(5, 10)
circ = Circle(7)
gen_shape = Shape()

# Demonstrating polymorphic behavior
print_shape_area(rect)   # Output: Area of the rectangle: 50
print_shape_area(circ)   # Output: Area of the circle: 153.94
print_shape_area(gen_shape) # Output: Area of a generic shape

# Another example: treating objects through their common base class
shapes = [rect, circ, gen_shape]
for s in shapes:
    s.area() # The correct 'area' method for each object is called

Explanation of the Code:

  1. class Shape:: This is the base class with a generic area() method and a display_area() method that calls area().
  2. class Rectangle(Shape): and class Circle(Shape):: These are derived classes that inherit from Shape.
  3. def area(self): ... (in Rectangle and Circle): Both Rectangle and Circle override the area() method to provide specific implementations for calculating their respective areas.
  4. def print_shape_area(shape):: This function takes any Shape object as an argument. When shape.display_area() is called, the area() method that is actually executed depends on the runtime type of the shape object (whether it's a Rectangle, a Circle, or a generic Shape). This is polymorphism in action.
  5. The loop at the end demonstrates how you can treat a list of different Shape objects uniformly. When s.area() is called on each object, the appropriate area() method for that specific type is executed.

Diagram (Conceptual):

+----------+
|  Shape   |
+----------+
| +area()  |
| +display_area()|
+----------+
      ^
      | (inherits from)
      |
+-----------+         +--------+
| Rectangle |         | Circle |
+-----------+         +--------+
| +width    |         | +radius|
| +height   |         |        |
| +area()   |         | +area()|
+-----------+         +--------+

The 'print_shape_area' function can accept either a 'Rectangle' or a 'Circle' object (because they are both types of 'Shape'). When 'shape.display_area()' is called, the specific 'area()' method of the actual object ('Rectangle's area calculation or 'Circle's area calculation) is executed.

Links to External Resources: