0% found this document useful (0 votes)
8 views4 pages

Java Polymorphism Explained with Examples

Polymorphism in Java allows a single action to be performed in different ways, exemplified by the 'sound()' method in the Animal class and its subclasses Horse and Cat, which provide their own implementations. This concept includes runtime polymorphism, where the method called is determined at runtime, and compile-time polymorphism, demonstrated through method overloading. The document also provides complete code examples for both runtime and compile-time polymorphism.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views4 pages

Java Polymorphism Explained with Examples

Polymorphism in Java allows a single action to be performed in different ways, exemplified by the 'sound()' method in the Animal class and its subclasses Horse and Cat, which provide their own implementations. This concept includes runtime polymorphism, where the method called is determined at runtime, and compile-time polymorphism, demonstrated through method overloading. The document also provides complete code examples for both runtime and compile-time polymorphism.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Polymorphism in Java with example

Polymorphism is one of the OOPs feature that allows us to perform a single


action in different ways. For example, lets say we have a class Animal that has a
method sound(). Since this is a generic class so we can’t give it a implementation
like: Roar, Meow, Oink etc. We had to give a generic message.

public class Animal{


...
public void sound(){
[Link]("Animal is making a sound");
}
}
Now lets say we two subclasses of Animal class: Horse and Cat that extends
(see Inheritance) Animal class. We can provide the implementation to the same
method like this:

public class Horse extends Animal{


...
@Override
public void sound(){
[Link]("Neigh");
}
}
and

public class Cat extends Animal{


...
@Override
public void sound(){
[Link]("Meow");
}
}
As you can see that although we had the common action for all
subclasses sound() but there were different ways to do the same action. This is a
perfect example of polymorphism (feature that allows us to perform a single
action in different ways). It would not make any sense to just call the generic
sound() method as each Animal has a different sound. Thus we can say that the
action this method performs is based on the type of object.

What is polymorphism in programming?


Polymorphism is the capability of a method to do different things based on the
object that it is acting upon. In other words, polymorphism allows you define one
interface and have multiple implementations. As we have seen in the above
example that we have defined the method sound() and have the multiple
implementations of it in the different-2 sub classes.
Which sound() method will be called is determined at runtime so the example we
gave above is a runtime polymorphism example.

Types of polymorphism and method overloading & overriding are covered in the
separate tutorials. You can refer them here:
1. Method Overloading in Java – This is an example of compile time (or static
polymorphism)
2. Method Overriding in Java – This is an example of runtime time (or dynamic
polymorphism)
3. Types of Polymorphism – Runtime and compile time – This is our next tutorial
where we have covered the types of polymorphism in detail. I would recommend
you to go though method overloading and overriding before going though this
topic.

Lets write down the complete code of it:

Example 1: Polymorphism in Java


Runtime Polymorphism example:
[Link]

public class Animal{


public void sound(){
[Link]("Animal is making a sound");
}
}
[Link]

class Horse extends Animal{


@Override
public void sound(){
[Link]("Neigh");
}
public static void main(String args[]){
Animal obj = new Horse();
[Link]();
}
}
Output:

Neigh
[Link]
public class Cat extends Animal{
@Override
public void sound(){
[Link]("Meow");
}
public static void main(String args[]){
Animal obj = new Cat();
[Link]();
}
}
Output:

Meow

Example 2: Compile time Polymorphism


Method Overloading on the other hand is a compile time polymorphism example.

class Overload
{
void demo (int a)
{
[Link] ("a: " + a);
}
void demo (int a, int b)
{
[Link] ("a and b: " + a + "," + b);
}
double demo(double a) {
[Link]("double a: " + a);
return a*a;
}
}
class MethodOverloading
{
public static void main (String args [])
{
Overload Obj = new Overload();
double result;
Obj .demo(10);
Obj .demo(10, 20);
result = Obj .demo(5.5);
[Link]("O/P : " + result);
}
}
Here the method demo() is overloaded 3 times: first method
has 1 int parameter,
second method has 2 int parameters and third one is having double parameter.
Which method is to be called is determined by the arguments we pass while
calling methods. This happens at runtime compile time so this type of
polymorphism is known as compile time polymorphism.

Output:

a: 10
a and b: 10,20
double a: 5.5
O/P : 30.25

Common questions

Powered by AI

Method overloading differs from method overriding primarily in the types of polymorphism they represent. Overloading is compile-time polymorphism, where multiple methods with the same name have different parameter lists within the same class. The method invoked is determined by the parameters passed at compile time. Overloading is useful for providing various ways to perform similar tasks, such as in mathematical calculations where methods operate on different data types. Method overriding, on the other hand, represents runtime polymorphism, where a subclass provides a specific implementation of a method declared in its superclass, useful in scenarios where actions need to differ based on object types, such as varying behaviors among different animal types calling their respective sound methods .

The @Override annotation in Java is significant because it alerts the compiler that the method is intended to override a method in a superclass. This provides two main benefits: it improves code readability and helps catch errors during compile time by ensuring that the method indeed overrides a superclass method. If there is no corresponding method in the superclass to override, the compiler will generate an error, preventing potential run-time issues .

Polymorphism in Java allows a single action, such as a method call, to be executed in different ways depending on the object that invokes the method. This is achieved through method overriding, which is demonstrated in the example where the class Animal has a method sound(). The subclasses Horse and Cat override this method, providing their own implementations (Neigh and Meow, respectively). The specific implementation of the sound() method that gets executed depends on the actual object type at runtime, exemplifying runtime polymorphism .

Polymorphism provides several advantages in a Java program, including improved code maintenance and flexibility. It allows for the implementation of a single interface with multiple methods, thus ensuring that code can be extended and changed with minimal disruption. This is particularly beneficial in large programs where maintaining consistency across different parts becomes easier. Polymorphism also facilitates code reuse and can help prevent the coupling of classes, leading to more modular and maintainable code .

Method overriding supports dynamic method dispatch in Java by allowing a subclass to provide a specific implementation of a method that is declared in its superclass. Dynamic method dispatch ensures that the overridden method that executes is based on the runtime type of the object, not the compile-time type. For example, if we have a superclass Animal with a method sound(), and subclasses Horse and Cat that override this method, creating an instance of Horse and calling sound() on an Animal reference like Animal obj = new Horse(); obj.sound(); will invoke the Horse's implementation of sound(), demonstrating runtime polymorphism through dynamic method dispatch .

Runtime polymorphism contributes to software extensibility by allowing new classes and methods to be introduced without modifying existing code, which facilitates the extension of functionalities. This is achieved through dynamic method dispatch, where method calls are determined at runtime, allowing new behavior to be incorporated simply by creating new subclasses. For example, in a graphics application that draws different shapes, adding a new shape only requires implementing a new subclass with its specific drawing behavior, without altering the core application logic that manages the list of shapes, making the system extensible and scalable .

Method overloading in Java illustrates compile-time polymorphism by allowing multiple methods with the same name but different parameter lists to exist within the same class. The method to be executed is determined at compile time based on the method signature, which includes the method name and parameters. In contrast, runtime polymorphism, achieved through method overriding, determines the method to be executed at runtime based on the actual object type. For instance, in the class Overload, the method demo() is overloaded with different parameters, and the choice of which method to call is made at compile time based on the arguments provided .

Polymorphism enhances object-oriented design patterns by allowing objects to be treated as instances of their parent class, making it easier to introduce new implementations and keep code open for extension but closed for modification. The Strategy design pattern exemplifies polymorphism: it allows different algorithms to be selected at runtime. Consider a context class that uses a strategy to execute a certain behavior; through polymorphism, different strategy implementations can be switched interchangeably without modifying the context class itself. For instance, various sorting algorithms such as QuickSort or MergeSort can implement a sort interface, enabling dynamic changes of sort strategy [unrelated to the specific examples from sources].

Polymorphism can be applied in non-object-oriented programming languages through mechanisms such as ad-hoc polymorphism or parametric polymorphism. For instance, in functional programming, polymorphism is often achieved through generics, which allow functions to operate on any data type. Similarly, languages like C support polymorphism through function pointers and templates. These methods enable functions to accept a variety of input types and perform type-specific operations, achieving polymorphic behavior even without traditional inheritance-based polymorphism found in object-oriented languages [general programming knowledge].

One challenge of using polymorphism in Java is the potential for increased complexity and runtime errors due to incorrect type assumptions, which can lead to unintended method calls. To address these issues effectively, developers can use design patterns such as the Factory pattern to validate object creation at runtime, leveraging robust testing to ensure correct type handling. Additionally, using proper documentation and code comments can alleviate confusion regarding method implementations across an inheritance hierarchy, thus helping maintain clarity and reducing errors [general programming best practices].

You might also like