Introduction: Polymorphism in Java
The word Polymorphism is derived from two greek words: poly and morphs. “Poly” means many and “morphs” means forms. So Polymorphism means “many forms”.
Polymorphism is one of the most important tenets of OOPS.We can perform an action in different ways. For example we can perform the add operation in many ways based on the input argument.
Two Ways to Shape Polymorphism in Java:-
- Compile Time Polymorphism: Method Overloading/Static Binding/Early Binding.
- Runtime Polymorphism:Method Overriding/Dynamic Binding/ Late Binding.
Compile Time Polymorphism in Java: Method Overloading/Static Binding/Early Binding
Compile time polymorphism, also known as static polymorphism or method overloading, is a form of polymorphism in Java where multiple methods with the same name but different parameters are defined within a class.
Here, the object type determination(binding) happens at compile time and hence it is also called as early binding.Private, static and final methods can be only overloaded as they can not be overridden.
Here, we define two or more methods with same name but with different parameters.The return type may or may not be same.
Compile Time Polymorphism in Java Example
Rules for Overloading
1) Method signature consists of number of arguments, type of arguments and order of arguments if they are of different types.We need to change the method signature to overload a method.
2) Return type of method is never part of method signature, so only changing the return type of method does not amount to method overloading.
3) Overloaded method can throw the same exception, a different exception or it simply does not throw any exception; no effect at all on method loading.
Runtime Polymorphism in Java:Method Overriding/Dynamic Binding/ Late Binding
This happens when the java compiler is not able to resolve the binding for the method call at the compile time as the method is defined in parent and also overridden in child classes.So at the runtime the actual object is used to identify the method call.
Runtime Polymorphism in Java Example
Let’s take an example:- Here the parent is Animal and Dog and Cat are it’s child classes.
Rules for Overriding
1) The method argument list(number of arguments, type of arguments and order of arguments) in overridden and overriding methods must be exactly same.
2) The return type of overriding method can be child class of return type declared in overridden method.
3) Above all rules, private, static and final methods can not be overridden in java in any way. As simple as that !!
4) Overriding method can not throw checked Exception higher in hierarchy than thrown by overridden method. Let’s say for example overridden method in parent class throws
FileNotFoundException, the overriding method in child class can throw
FileNotFoundException; but it is not allowed to throw
Exception are higher in hierarchy i.e. super classes of
5) Also note that overriding method can not reduce the access scope of overridden method. Put in simple words, if overridden method in parent class is protected, then overriding method in child class can not be private. It must be either protected (same access) or public (wider access).
Key Advantages of Polymorphism in Java
Polymorphism in Java offers several significant benefits that contribute to the flexibility, extensibility, and maintainability of code. Here are some key advantages:
- Code Reusability: Polymorphism allows for the creation of code that can be reused across multiple classes and objects. By designing classes with common interfaces or superclasses, methods can be written to accept objects of those types, enabling the same code to be used with different implementations.
- Flexibility and Extensibility: Polymorphism enables the addition of new classes or behaviors without modifying existing code. New classes can be created that inherit from existing superclasses or implement common interfaces, seamlessly integrating into the existing codebase.
- Modularity and Organized Design: Polymorphism promotes modular design principles by separating the behavior and implementation details of classes. It allows developers to focus on specific functionalities in individual classes while maintaining a unified interface for interaction with other classes.
- Simplified Code Maintenance: Polymorphism reduces code duplication by providing a unified interface for common behaviors. When changes are required, modifications can be made in a centralized manner, minimizing the need to modify code in multiple places.
- Runtime Flexibility: Polymorphism enables dynamic method dispatch, allowing the appropriate method implementation to be determined at runtime based on the actual object type. This dynamic binding supports polymorphic behavior and facilitates the implementation of complex and customizable runtime scenarios.
- Code Readability and Understandability: Polymorphism enhances code readability by promoting a more intuitive and natural representation of real-world relationships. It allows developers to write code that reflects the underlying concepts and relationships between different entities in a more straightforward and expressive manner.
- Enhanced Testability: Polymorphism facilitates the creation of testable code by allowing the use of mock objects or test doubles that implement the same interface or extend the same superclass. This enables easier isolation and testing of individual components and promotes effective unit testing practices.
- Polymorphic Collections: Polymorphism is often leveraged in the Java Collections Framework, enabling the creation of collections that can hold objects of different subclasses but share a common superclass or interface. This simplifies the handling and manipulation of collections with heterogeneous objects.
Overall, polymorphism in Java empowers developers to write flexible, modular, and reusable code. It supports the principles of abstraction and encapsulation, allowing for effective code organization and maintenance. By leveraging polymorphism, developers can build robust and scalable applications that are easier to understand, extend, and maintain.
Real Life Examples for Polymorphism in Java
Here are a few real-life examples that showcase the use of polymorphism in Java:
- Animal Hierarchy: Consider a scenario where you have different types of animals such as dogs, cats, and birds. You can create an
Animalsuperclass with common attributes and behaviors. Each specific animal type can inherit from this superclass and override methods like
move(). This allows you to treat all animals uniformly and perform common operations on them, regardless of their specific type.
- Media Player: In a media player application, you may have different types of media files like audio files, video files, and image files. You can create a common interface called
MediaPlayerand define methods like
stop(). Each media file type can implement this interface and provide its own implementation of these methods. By programming against the
MediaPlayerinterface, you can handle different media files uniformly, allowing users to interact with them in a consistent manner.
- Shape Rendering: In a graphics application, you may have different types of shapes to render, such as circles, rectangles, and polygons. You can create a
Shapeinterface or superclass with a method like
draw(). Each specific shape class can implement this method and provide its own logic to render the shape. By treating all shapes as instances of the
Shapeinterface or superclass, you can render them uniformly without knowing their specific implementation details.
- Vehicle Transportation: In a transportation system, you may have different types of vehicles like cars, bicycles, and motorcycles. You can define a common interface or superclass called
Vehiclewith methods like
stop(). Each vehicle type can implement these methods based on their unique characteristics. By programming against the
Vehicleinterface or superclass, you can control and manage different vehicles in a consistent manner.
- Banking Transactions: In a banking application, you may have different types of transactions like deposits, withdrawals, and transfers. You can create a common interface called
Transactionand define methods like
execute(). Each transaction type can implement this interface and provide its own logic to perform the specific transaction. By treating all transactions as instances of the
Transactioninterface, you can handle them uniformly, simplifying transaction processing and management.
These real-life examples demonstrate how polymorphism enables the treatment of different objects uniformly through a common interface or superclass. By leveraging polymorphism, you can write code that is flexible, reusable, and extensible, accommodating various types and behaviors in a consistent manner.
FAQs about Polymorphism in Java
Q: What is polymorphism in Java?
A: Polymorphism in Java refers to the ability of objects of different classes to be treated as objects of a common superclass or interface. It allows for code flexibility and reusability through a unified interface.
Q: What is the difference between compile-time polymorphism and runtime polymorphism in Java?
A: Polymorphism in Java includes both compile-time polymorphism, achieved through method overloading, and runtime polymorphism, achieved through method overriding. Compile-time polymorphism is determined during compilation, while runtime polymorphism is resolved at runtime based on the actual object type.
Q: How is polymorphism achieved in Java?
A: Polymorphism in Java is achieved through inheritance, method overriding, and method overloading. Inheritance allows objects of a subclass to be treated as objects of their superclass, while method overriding enables a subclass to provide its own implementation of a method inherited from the superclass.
Q: What is method overloading in Java polymorphism?
A: Method overloading, a form of polymorphism in Java, allows multiple methods with the same name but different parameter lists to exist within a class. The appropriate method is chosen during compilation based on the arguments passed.
Q: What is method overriding in Polymorphism in Java?
A: Method overriding, a key aspect of polymorphism in Java, occurs when a subclass provides its own implementation of a method already defined in its superclass. The subclass method must have the same name, return type, and parameter list as the superclass method.
Q: Can a subclass method override multiple methods from its superclass in Polymorphism in Java?
A: Yes, a subclass method in Polymorphism in Java can override multiple methods from its superclass as long as they have different method signatures. Each method in the subclass must adhere to the overriding rules, matching the method signature of the superclass method it intends to override.
Q: Can static methods be overridden in Polymorphism in Java?
A: No, static methods cannot be overridden in Polymorphism in Java. They are resolved based on the reference type at compile-time rather than the actual object type at runtime. Subclasses can declare methods with the same signature, but it is considered method hiding rather than overriding.
Q: What is the significance of the “super” keyword in method overriding in Polymorphism in Java?
A: In Polymorphism in Java, the “super” keyword is used to refer to the superclass version of a method. It is employed to invoke the superclass’s method implementation when a method is overridden in the subclass. This allows for the reuse of superclass behavior in the subclass.
Q: Can constructors be overridden in Polymorphism in Java?
A: No, constructors cannot be overridden in Polymorphism in Java. Each class must define its own constructors, and they are not inherited like methods. However, a subclass constructor can invoke the constructor of its superclass using the “super” keyword.
Q: How does polymorphism contribute to code reusability and extensibility in Java?
A: Polymorphism in Java enhances code reusability and extensibility by allowing objects of different classes to be treated uniformly through a common interface or superclass. This simplifies code maintenance, promotes modular design, and enables the addition of new classes without modifying existing code that relies on the common interface or superclass.
Q: What is dynamic method dispatch in Polymorphism in Java?
A: Dynamic method dispatch in Polymorphism in Java refers to the mechanism where the specific implementation of a method is determined at runtime based on the actual object type rather than the reference type. It allows for the invocation of overridden methods and enables polymorphic behavior in Java.
Q: Can we override a method and change its return type in Polymorphism in Java?
A: No, it is not possible to change the return type of a method during method overriding in Polymorphism in Java. The return type of the overriding method must be the same or a subtype of the return type in the superclass.
Q: Can we have polymorphism without inheritance in Java?
A: Polymorphism in Java is closely associated with inheritance, but it is possible to achieve polymorphic behavior without direct inheritance by utilizing interfaces. Interfaces allow unrelated classes to implement common methods, enabling them to be treated polymorphically.
Q: Can we overload methods based on their return types in Polymorphism in Java?
A: No, Polymorphism in Java does not support method overloading based solely on different return types. Method overloading is determined by the number, types, and order of the method’s parameters.
Q: Is polymorphism applicable only to instance methods in Polymorphism in Java?
A: No, polymorphism in Polymorphism in Java is applicable to both instance methods and static methods. However, the selection of the appropriate method is determined by the type of the object at runtime for instance methods and by the reference type at compile-time for static methods.
These FAQs cover a wide range of questions related to polymorphism in Java, providing valuable insights into its concepts, behavior, and usage.
Throughout this article, we explored the concept of polymorphism in Java, which involves inheritance, method overriding, and dynamic method dispatch.
Understanding and effectively utilizing polymorphism in Java is essential for writing robust, flexible, and scalable software solutions. It promotes code reuse, enhances code readability, and simplifies complex programming scenarios.