Understanding Polymorphism

Understanding Polymorphism | Java

Polymorphism is a fundamental concept in the world of object-oriented programming (OOP) and plays a crucial role in Java. In this comprehensive article, we’ll explore what polymorphism is, how it is achieved in Java, and dive into practical use cases and examples.

What is Polymorphism?

Polymorphism, derived from the Greek words “poly” (many) and “morphos” (forms), refers to the ability of objects of different classes to be treated as objects of a common superclass. It allows you to write code that can work with objects of multiple types, enabling flexibility and extensibility in your Java applications.

Polymorphism is closely related to two key concepts: method overriding and interfaces. In Java, polymorphism is implemented through method overriding and interfaces, allowing different classes to provide their own implementations for methods defined in a common interface or superclass.

How to achieve Polymorphism?

Polymorphism in Java is achieved through method overriding, method overloading and interfaces. Let’s explore these concepts in more detail.

Method Overriding

Method overriding is a feature in Java that allows a subclass to provide a specific implementation for a method that is already defined in its superclass. The overriding method should have the same method signature (name, parameters, and return type) as the method in the superclass.

class Animal 
{
    void makeSound() 
    {
        System.out.println("Some sound");
    }
}

class Dog extends Animal 
{
    @Override
    void makeSound() 
    {
        System.out.println("Bark");
    }
}

class Cat extends Animal 
{
    @Override
    void makeSound() 
    {
        System.out.println("Meow");
    }
}

In this example, the makeSound() method is overridden in the Dog and Cat subclasses, providing specific implementations for each animal type.

Method Overloading

Method overloading is another way to achieve a form of polymorphism in Java known as “compile-time polymorphism” or “method overloading polymorphism”. Method overloading occurs when a class defines multiple methods with the same name but different parameter lists (i.e., a different number of parameters, or parameters of different types). The Java compiler determines which overloaded method to call at compile time based on the number and types of arguments passed during method invocation.

class Calculator 
{
    int add(int a, int b) 
    {
        return a + b;
    }

    double add(double a, double b) 
    {
        return a + b;
    }
}

In the example above, the Calculator class has two overloaded add methods. The compiler decides which method to call based on the argument types when you invoke the add method.

Method overloading polymorphism vs Method overriding polymorphism

  • Compile time vs Runtime
    • Method overloading polymorphism is resolved at compile time, whereas method overriding polymorphism is resolved at runtime.
  • Static Binding
    • Method overloading is also known as “static polymorphism” because the decision about which method to call is made at compile time, and it’s based on the reference type and the method’s signature.
  • No inheritance or Interfaces
    • Method overloading does not require inheritance or interface implementation; it relies solely on method names and parameter lists.

Interfaces

Interfaces in Java define a contract that classes must adhere to by implementing all the methods declared in the interface. Multiple classes can implement the same interface, allowing polymorphic behavior.

interface Drawable 
{
    void draw();
}

class Circle implements Drawable 
{
    @Override
    public void draw() 
    {
        System.out.println("Drawing a circle");
    }
}

class Square implements Drawable 
{
    @Override
    public void draw() 
    {
        System.out.println("Drawing a square");
    }
}

In this example, both the Circle and Square classes implement the Drawable interface, providing their own implementations of the draw() method.

Use cases and Benefits of Polymorphism

Polymorphism has several practical use cases and benefits in programming.

  • Code Reusability
  • Polymorphism promotes code reusability by allowing different classes to implement common interfaces or inherit from a common superclass. This reduces code duplication and makes maintenance easier.
  • Extensibility
  • You can add new classes that implement existing interfaces or inherit from existing superclasses without modifying existing code. This makes your codebase more extensible.
  • Flexibility
  • Polymorphism allows you to write code that can work with objects of different types, making your code more adaptable to varying data and requirements.
  • Polymorphic Collections
  • ou can create collections (e.g., lists or arrays) of objects that share a common interface or superclass. This simplifies data management and enables you to process objects uniformly.
  • Runtime Binding
  • Polymorphism enables dynamic method binding, where the appropriate method is determined at runtime based on the actual type of the object, not just its declared type.

Example for Polymorphism

1. Shape Hierarchy

abstract class Shape 
{
    abstract void draw();
}

class Circle extends Shape 
{
    @Override
    void draw() 
    {
        System.out.println("Drawing a circle");
    }
}

class Rectangle extends Shape 
{
    @Override
    void draw() 
    {
        System.out.println("Drawing a rectangle");
    }
}

In this example, both Circle and Rectangle inherit from the Shape superclass and override the draw() method.

2. Vehicle Categorization

interface Vehicle 
{
    void start();
    void stop();
}

class Car implements Vehicle 
{
    @Override
    public void start() 
    {
        System.out.println("Car started");
    }

    @Override
    public void stop() 
    {
        System.out.println("Car stopped");
    }
}

class Bike implements Vehicle 
{
    @Override
    public void start() 
    {
        System.out.println("Bike started");
    }

    @Override
    public void stop() 
    {
        System.out.println("Bike stopped");
    }
}

Here, both Car and Bike implement the Vehicle interface, providing their own implementations for start() and stop().

Let’s discuss about Inheritance in next article.

Leave a Reply

Your email address will not be published. Required fields are marked *