Polymorphism means one entity existing in multiple forms. It provides flexibility to application systems. It simplifies coding and reduces the rework involved in modifying and developing an application. It refers to the ability of an object to take on different forms depending upon the situation.
According to the polymorphism design principle, the same message sent to different objects results in different behavior. The behavior depends on the type of object that receives the message.
Every key of a keyboard performs a specific action when a keystroke message is generated for that key. However, by using polymorphism, the same code with a small change can be used by different keys of the keyboard to trigger specific actions.
Polymorphism and Classes
In Java, type polymorphism may be implemented using class inheritance, interface implementation, or both. When using class inheritance to implement polymorphism, a class instance may take the form of itself, or any of its superclasses.
[Refer above Fig 1.1] When an instance of a class is created, it may always be referenced using its own type. Although this seems obvious, it is important because it is one of the forms that the object instance may take. In addition, since every class in Java has the class Object as a base class, the instance may also always be referenced as an Object.
When a class has a superclass, an instance of the class may also be referenced as if it is the superclass. For example, if a class Car is derived from the class Vehicle, an instance of Car may be referenced as a Vehicle. The possible type references for an instance of the Car class are shown below [Refer Fig 1.2].
[Refer Fig 1.3] A class instance can be referenced as any of the superclass types regardless of the depth of the inheritance
The class Mustang, which derives from Car, which derives from Vehicle. Here an Instance of the Mustang class may be referenced as any of its superclasses.
An instance of a class is also considered an instance of its superclass. The ‘instanceof’ operator can be used to show this relationship. When an object is an instance of a class, it is called an is-a relationship. The below example shows that the instance of the Mustang class, is also an instance of all of its superclasses. [Refer Fig 1.4,1.4a]
Polymorphism and Interfaces
When an instance of a class is created, it may always be referenced using its own type. Refer Fig 2.1
If a class implements an interface, it may be referenced as the interface type. For example, a class CDPlayer implements MusicPlayer interface.[Refer Fig 2.2]
A class may implement as many interfaces as necessary. The example [Refer Fig 2,3] shows a new interface called MusicRecorder. The class CDPlayerRecorder implements the MusicPlayer and MusicRecorder interfaces.
When a class implements multiple interfaces, an instance of the class is considered an instance of the interfaces that it implements. Therefore, the class can be referenced as if it is any of its implemented interfaces.[Refer Fig 2.4]
An interface may extend other interfaces. When an interface extends other interfaces, a class that implements the interface also implements the extended interfaces. An instance of the class may be referenced using any of the interfaces, including the extended interfaces.[Refer Fig 2.5]
If a class has a superclass that implements an interface, an instance of the class may be referenced using the interface type.
Example: We have a CDPlayer class that implements the MusicPlayer interface. If we have a class CustomCDPlayer that derives from the CDPlayer class, the instance of the CustomCDPlayer may be referenced as a MusicPlayer. [Refer Fig 2.6]
Since a class may have superclasses as well as implemented interfaces, it therefore may be referenced both as superclass types and interface types.
Example: [Refer Fig 2.6] a CustomCDPlayer instance may be referenced using both the superclass CDPlayer, and the interface MusicPlayer.
Valid Variable Assignments
Java allows you to assign variables of a derived class with the instances of the base class and vice versa.
When a derived class extends a base class, the derived class inherits all the members of the base class. It may also contain some additional methods and fields. In Java, you can assign an instance of the derived class to a variable type of base class.
Example: [Refer Fig 3.1]
Consider a class Wind that extends class Instrument. In this case, the class Wind inherits the methods of the class Instrument. In this case, the Wind derived class is a superset of the base class Instrument. It might contain more methods than the base class.
It refers to assigning a variable of a base class to an instance of a derived class. This implies that the variables of the base class can be initialized to the base class or to one of the derived classes. [Refer Fig 3.2] If class Wind extends Instrument, you can initialize the variables of class Instrument to the instances of class Wind or class Instrument.
When downcasting, you should explicitly indicate a variable of type Brass to one of the variables of type Instrument. A faulty cast construct can cause a run-time error. If a base class is assigned to a derived class without a cast construct, it can lead to a compilation error. [Refer Fig 3.3]