# What is Polymorphism?

### What is Polymorphism?

Polymorphism is the ability of a single interface to represent different underlying forms (data types). It allows one interface to be used for a general class of actions, and the specific action is determined at runtime or compile time.

Polymorphism can be achieved through:

1. **Method Overloading**: Multiple methods with the same name but different parameters.
2. **Method Overriding**: A child class redefines a method inherited from the parent class.

### Example: Method Overriding in Java

Let's use a real-life scenario to demonstrate polymorphism through method overriding.

Consider a base class `Employee` and two derived classes `Manager` and `Developer`. Both classes will have a method `calculateSalary`, but the way salary is calculated will differ between a Manager and a Developer.

**Code Example:**

```java
// Base class
class Employee {
    protected String name;
    protected int baseSalary;

    public Employee(String name, int baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }

    // Method to be overridden
    public int calculateSalary() {
        return baseSalary;
    }
}

// Derived class Manager
class Manager extends Employee {
    private int bonus;

    public Manager(String name, int baseSalary, int bonus) {
        super(name, baseSalary);
        this.bonus = bonus;
    }

    // Overriding the calculateSalary method
    @Override
    public int calculateSalary() {
        return baseSalary + bonus;
    }
}

// Derived class Developer
class Developer extends Employee {
    private int projectAllowance;

    public Developer(String name, int baseSalary, int projectAllowance) {
        super(name, baseSalary);
        this.projectAllowance = projectAllowance;
    }

    // Overriding the calculateSalary method
    @Override
    public int calculateSalary() {
        return baseSalary + projectAllowance;
    }
}

public class Main {
    public static void main(String[] args) {
        Employee emp1 = new Manager("Alice", 5000, 2000);
        Employee emp2 = new Developer("Bob", 4000, 1000);

        System.out.println(emp1.name + "'s Salary: " + emp1.calculateSalary()); // Outputs: Alice's Salary: 7000
        System.out.println(emp2.name + "'s Salary: " + emp2.calculateSalary()); // Outputs: Bob's Salary: 5000
    }
}
```

#### Explanation

1. **Base Class `Employee`**:
   * Has a method `calculateSalary` which returns the `baseSalary`.
2. **Derived Class `Manager`**:
   * Extends `Employee`.
   * Overrides `calculateSalary` to add a bonus to the base salary.
3. **Derived Class `Developer`**:
   * Extends `Employee`.
   * Overrides `calculateSalary` to add a project allowance to the base salary.
4. **Main Class**:
   * Creates instances of `Manager` and `Developer`.
   * Calls `calculateSalary` on both instances, demonstrating that the method behaves differently based on the object's class type, even though it is called on the base class reference (`Employee`).

#### Use Cases of Polymorphism

1. **UI Components**:
   * Different types of UI components (buttons, text fields) can be treated uniformly but will have specific implementations for rendering or handling events.
2. **Game Development**:
   * Different types of game characters (players, enemies) can be managed using a common interface but will have specific behaviors (move, attack).
3. **Payment Systems**:
   * Different types of payment methods (credit card, PayPal) can be processed using a common interface but will have specific processing details.

Polymorphism allows for code that is more flexible and easier to maintain. It helps in building systems that can grow and change over time without requiring a complete rewrite of the existing code.

***

### Method Overloading

Method overloading is a feature in Java (and other programming languages) that allows a class to have more than one method with the same name, as long as their parameter lists are different. It is a compile-time polymorphism concept, meaning the compiler determines which method to call based on the method signature.

**Key Points:**

* **Method Signature**: Consists of the method name and parameter list.
* **Return Type**: Can be different, but it does not affect method overloading.
* **Parameter List**: Must be different (in number, type, or both).

### Example: Method Overloading in Java

Let's use a simple real-life scenario where we calculate the salary of an employee. Sometimes, we might need to include a festive bonus in the salary calculation.

**Code Example:**

```java
class Employee {
    private String name;
    private int baseSalary;

    public Employee(String name, int baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }

    // Method to calculate salary without bonus
    public int calculateSalary(int daysWorked) {
        return baseSalary * daysWorked;
    }

    // Overloaded method to calculate salary with bonus
    public int calculateSalary(int daysWorked, int festiveBonus) {
        return (baseSalary * daysWorked) + festiveBonus;
    }

    public static void main(String[] args) {
        Employee emp = new Employee("John", 100);

        // Calculate salary without bonus
        int salaryWithoutBonus = emp.calculateSalary(20);
        System.out.println("Salary without bonus: " + salaryWithoutBonus); // Outputs: Salary without bonus: 2000

        // Calculate salary with bonus
        int salaryWithBonus = emp.calculateSalary(20, 500);
        System.out.println("Salary with bonus: " + salaryWithBonus); // Outputs: Salary with bonus: 2500
    }
}
```

#### Explanation

1. **Class `Employee`**:
   * **Attributes**: `name` and `baseSalary` are the attributes of the class.
   * **Constructor**: Initializes the `name` and `baseSalary` of the employee.
2. **Method `calculateSalary` (without bonus)**:
   * Takes `daysWorked` as a parameter.
   * Returns the total salary based on the days worked.
3. **Overloaded Method `calculateSalary` (with bonus)**:
   * Takes `daysWorked` and `festiveBonus` as parameters.
   * Returns the total salary including the festive bonus.
4. **Main Method**:
   * Creates an instance of `Employee`.
   * Calls `calculateSalary` method twice with different parameters to demonstrate method overloading.

#### Use Cases of Method Overloading

1. **Payment Calculations**:
   * Different methods for calculating payment with or without additional charges (like taxes or discounts).
2. **Data Parsing**:
   * Overloaded methods to parse data from different sources (strings, files, databases).
3. **Search Functionality**:
   * Different methods for searching based on different criteria (by name, by ID, by attributes).

Method overloading increases the readability of the code by providing a way to call the same method in different contexts. It makes the program more intuitive and easier to maintain, as similar operations can be grouped under the same method name.
