Polymorphism is one of the core concepts of Object-Oriented Programming (OOP) in Java. It allows objects to be treated as instances of their parent class rather than their actual class. This enables a single interface to represent different underlying forms (data types).
Key Concepts of Polymorphism
- Method Overloading: This is a compile-time polymorphism where multiple methods have the same name but different parameters.
- Method Overriding: This is a runtime polymorphism where a subclass provides a specific implementation of a method that is already defined in its superclass.
- Polymorphic Variables: Variables that can hold references to objects of different types at different times during the execution of a program.
Method Overloading
Method overloading allows a class to have more than one method with the same name, as long as their parameter lists are different.
Example of Method Overloading
public class MathOperations { // Method to add two integers public int add(int a, int b) { return a + b; } // Method to add three integers public int add(int a, int b, int c) { return a + b + c; } // Method to add two double values public double add(double a, double b) { return a + b; } public static void main(String[] args) { MathOperations math = new MathOperations(); System.out.println(math.add(2, 3)); // Output: 5 System.out.println(math.add(2, 3, 4)); // Output: 9 System.out.println(math.add(2.5, 3.5)); // Output: 6.0 } }
Explanation
- The
add
method is overloaded with different parameter lists. - The correct method is chosen at compile time based on the arguments passed.
Method Overriding
Method overriding allows a subclass to provide a specific implementation of a method that is already defined in its superclass.
Example of Method Overriding
class Animal { // Method to be overridden public void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { // Overriding the sound method @Override public void sound() { System.out.println("Dog barks"); } } public class Main { public static void main(String[] args) { Animal myDog = new Dog(); myDog.sound(); // Output: Dog barks } }
Explanation
- The
sound
method in theDog
class overrides thesound
method in theAnimal
class. - The
@Override
annotation is used to indicate that a method is being overridden. - The method to be executed is determined at runtime based on the object type.
Polymorphic Variables
Polymorphic variables can refer to objects of different types at different times.
Example of Polymorphic Variables
class Animal { public void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } } class Cat extends Animal { @Override public void sound() { System.out.println("Cat meows"); } } public class Main { public static void main(String[] args) { Animal myAnimal; myAnimal = new Dog(); myAnimal.sound(); // Output: Dog barks myAnimal = new Cat(); myAnimal.sound(); // Output: Cat meows } }
Explanation
- The variable
myAnimal
is of typeAnimal
but can refer to objects of typeDog
orCat
. - The method to be executed is determined at runtime based on the actual object type.
Practical Exercise
Exercise
Create a class hierarchy where Vehicle
is the superclass and Car
and Bike
are subclasses. Override a method move
in both subclasses to print specific messages.
Solution
class Vehicle { public void move() { System.out.println("Vehicle is moving"); } } class Car extends Vehicle { @Override public void move() { System.out.println("Car is moving"); } } class Bike extends Vehicle { @Override public void move() { System.out.println("Bike is moving"); } } public class Main { public static void main(String[] args) { Vehicle myVehicle; myVehicle = new Car(); myVehicle.move(); // Output: Car is moving myVehicle = new Bike(); myVehicle.move(); // Output: Bike is moving } }
Explanation
- The
move
method is overridden in bothCar
andBike
classes. - The
myVehicle
variable can refer to either aCar
or aBike
object, demonstrating polymorphism.
Common Mistakes and Tips
- Common Mistake: Forgetting to use the
@Override
annotation when overriding methods. This can lead to subtle bugs if the method signature does not match exactly. - Tip: Always use the
@Override
annotation to ensure that you are correctly overriding a method.
Conclusion
Polymorphism is a powerful feature in Java that allows for flexible and reusable code. By understanding and utilizing method overloading, method overriding, and polymorphic variables, you can write more dynamic and maintainable programs. In the next topic, we will delve into encapsulation, another fundamental concept of OOP.
Java Programming Course
Module 1: Introduction to Java
- Introduction to Java
- Setting Up the Development Environment
- Basic Syntax and Structure
- Variables and Data Types
- Operators
Module 2: Control Flow
Module 3: Object-Oriented Programming
- Introduction to OOP
- Classes and Objects
- Methods
- Constructors
- Inheritance
- Polymorphism
- Encapsulation
- Abstraction
Module 4: Advanced Object-Oriented Programming
Module 5: Data Structures and Collections
Module 6: Exception Handling
Module 7: File I/O
Module 8: Multithreading and Concurrency
- Introduction to Multithreading
- Creating Threads
- Thread Lifecycle
- Synchronization
- Concurrency Utilities
Module 9: Networking
- Introduction to Networking
- Sockets
- ServerSocket
- DatagramSocket and DatagramPacket
- URL and HttpURLConnection