Java Polymorphism

Polymorphism in Java is one of the core concepts of object-oriented programming (OOP). It allows objects to be treated as instances of their parent class rather than their actual class. Polymorphism means "many forms," and it enables a single action to behave differently based on the object that it is acting upon.

Key Topics

1. Method Overriding

Method overriding occurs when a subclass provides a specific implementation of a method that is already defined in its superclass. It allows the subclass to offer a specialized behavior.

Example:

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

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

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

2. Method Overloading

Method overloading allows a class to have multiple methods with the same name but different parameters. It's a type of compile-time polymorphism.

Example:

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

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

    public int add(int a, int b, int c) {
        return a + b + c;
    }
}

3. Runtime Polymorphism

Runtime polymorphism is achieved through method overriding and is also known as dynamic method dispatch. The method to be invoked is determined at runtime based on the object's actual type.

Example:

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myAnimal.makeSound(); // Outputs: Some generic animal sound
        myDog.makeSound();    // Outputs: Bark
        myCat.makeSound();    // Outputs: Meow
    }
}

4. Polymorphism with Interfaces

Interfaces can be used to achieve polymorphism by allowing classes to implement the same interface and provide different implementations for the methods.

Example:

public interface Shape {
    void draw();
}

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

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

public class Main {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Rectangle();

        shape1.draw(); // Outputs: Drawing a circle
        shape2.draw(); // Outputs: Drawing a rectangle
    }
}

Key Takeaways

  • Polymorphism allows objects to be treated as instances of their parent class.
  • Method overriding and method overloading are two ways to achieve polymorphism.
  • Runtime polymorphism enables dynamic method dispatch.
  • Interfaces facilitate polymorphism by allowing multiple classes to implement the same methods differently.