What is Polymorphism in OOP?

A conceptual guide to polymorphism, one of the four fundamental pillars of object-oriented programming. Learn how polymorphism allows objects of different classes to be treated as objects of a common superclass.

Polymorphism is one of the four fundamental principles of Object-Oriented Programming (OOP), alongside encapsulation, abstraction, and inheritance. The word "polymorphism" comes from Greek and means "many forms." In programming, it refers to the ability of a single interface to represent different underlying forms (data types).

At its core, polymorphism allows you to treat objects of different classes that share a common parent class as if they were objects of the parent class. This enables you to write more flexible and reusable code.

An Analogy: The Power Outlet

Think of an electrical outlet on your wall. It provides a standard interface for power. You can plug many different types of devices into it—a lamp, a laptop charger, a vacuum cleaner. Each of these devices does something different, but they all conform to the same standard interface (the plug).

The outlet doesn't need to know the specific details of the device. It just provides power. The device itself knows what to do with that power. This is polymorphism in action.

Polymorphism through Inheritance

The most common way to achieve polymorphism in OOP is through inheritance. Let's create a simple class hierarchy in C#.

First, we define a base Shape class with a virtual method called Draw().

public class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a generic shape.");
    }
}

Next, we create several derived classes that inherit from Shape and override the Draw() method to provide their own specific implementation.

public class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle.");
    }
}

public class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a rectangle.");
    }
}

public class Triangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a triangle.");
    }
}

The Power of Polymorphism

Now for the magic. We can create a list that holds Shape objects, but we can put instances of Circle, Rectangle, and Triangle into it. This is possible because they all are Shapes through inheritance.

var shapes = new List<Shape>
{
    new Circle(),
    new Rectangle(),
    new Triangle(),
    new Shape() // The base class itself
};

Now, we can loop through this list and call the Draw() method on each object. We can treat every object in the list simply as a Shape, without needing to know its specific, underlying type.

foreach (var shape in shapes)
{
    shape.Draw();
}

Output:

Drawing a circle.
Drawing a rectangle.
Drawing a triangle.
Drawing a generic shape.

This is polymorphism. Even though we are calling the same shape.Draw() method in each iteration, the program is smart enough to execute the correct, overridden version of Draw() based on the actual type of the object at runtime. We have one interface (shape.Draw()) that results in many different behaviors.

Why is Polymorphism Useful?

  • Flexibility and Extensibility: It allows you to write code that can work with new types without modification. If we create a new Pentagon class that inherits from Shape, our foreach loop above would work with it automatically, without any changes.

  • Simpler Code: You can write more generic and abstract code. Instead of having a long if-else if statement to check the type of each shape and call a different drawing function, you can just treat them all as Shapes and let polymorphism do the work.

  • Decoupling: It helps to decouple the code that uses an object from the specific implementations of that object.

Conclusion

Polymorphism is a cornerstone of object-oriented design. It allows you to write flexible, reusable, and maintainable code by enabling objects of different classes to be treated through a common interface. By leveraging inheritance and method overriding, polymorphism allows you to build systems that are easier to extend and adapt to new requirements over time.