What is "polymorphism" in OOP
Polymorphism is the property of a system to use objects with the same interface without information about the type and internal structure of the object.
The advantage of polymorphism is that it helps reduce program complexity by allowing the same interface to be used to define a single set of actions. The choice of a specific action, depending on the situation, rests with the compiler of the programming language. Hence the key feature of polymorphism is the use of an object of a derived class, instead of an object of the base class (descendants can change their parent behavior, even if they are accessed by reference of the parent type).
Any training in driving would not make sense if a person who learned to drive, say, a VAZ 2106 could not then drive a VAZ 2110 or BMW X3. On the other hand, it is difficult to imagine a person who could normally drive a car in which the gas pedal is to the left of the brake pedal, and instead of the steering wheel there is a joystick.
The thing is that the main controls of the car have the same design and principle of operation. The driver knows for sure that in order to turn left, he must turn the steering wheel, regardless of whether there is a power steering there or not. If a person needs to get from work to home, he will sit behind the wheel of a car and perform the same actions, regardless of what type of car he uses. In fact, we can say that all cars have the same interface, and the driver, abstracting from the essence of the car, works with this very interface. If the driver has to drive on the German Autobahn, he will probably choose a fast car with a low stance, and if he has to return from a distant maral in Gorny Altai after a rain, most likely, he will choose UAZ with army bridges. But, regardless of how the movement and internal functioning of the machine will be realized, the interface will remain the same.
A polymorphic variable is a variable that can take values of different types, and a polymorphic function is a function in which at least one argument is a polymorphic variable. There are two types of polymorphic functions:
- ad hoc, the function behaves differently for different types of arguments (for example, the draw() function - draws different types of shapes in different ways);
- parametric, the function behaves the same for arguments of different types (for example, the add() function - equally puts elements of different types into the container).
The principle in OOP when a program can use objects with the same interface without information about the internal structure of the object is called polymorphism.
Example:
Let's imagine that in our program we need to describe a user who can use any phone model to call another user. Here's how you can do it:
public class User {
private String name;
public User(String name) {
this.name = name;
}
public void callAnotherUser(int number, AbstractPhone phone) {
// here it is polymorphism -
// using the abstract type AbstractPhone phone in the code!
phone.call(number);
}
}
Now let's describe the different phone models. One of the first phone models:
public class ThomasEdisonPhone extends AbstractPhone {
public ThomasEdisonPhone(int year) {
super(year);
}
@Override
public void call(int outputNumber) {
System.out.println("Rotate the handle");
System.out.println("Provide subscriber number, sir");
}
@Override
public void ring(int inputNumber) {
System.out.println("The phone is ringing");
}
}
Regular landline phone:
public class Phone extends AbstractPhone {
public Phone(int year) {
super(year);
}
@Override
public void call(int outputNumber) {
System.out.println("Calling number" + outputNumber);
}
@Override
public void ring(int inputNumber) {
System.out.println("The phone is ringing");
}
}
And finally, a cool videophone:
public class VideoPhone extends AbstractPhone {
public VideoPhone(int year) {
super(year);
}
@Override
public void call(int outputNumber) {
System.out.println("I connect the video channel for the subscriber" + outputNumber);
}
@Override
public void ring(int inputNumber) {
System.out.println("You have an incoming video call ..." + inputNumber);
}
}
Let's create objects in the main() method and test the callAnotherUser method:
AbstractPhone firstPhone = new ThomasEdisonPhone(1879);
AbstractPhone phone = new Phone(1984);
AbstractPhone videoPhone = new VideoPhone(2018);
User user = new User("Andrey");
user.callAnotherUser(224466, firstPhone);
// Rotate the handle
// Give the subscriber number, sir
user.callAnotherUser(224466, phone);
// Call number 224466
user.callAnotherUser(224466, videoPhone);
// I connect the video channel for the subscriber 224466
By calling the same method on the user object, we got different results. The choice of a specific implementation of the call method inside the callAnotherUser method was made dynamically based on the specific type of the calling object during the program execution. This is the main advantage of polymorphism - the choice of implementation during program execution.
In the phone class examples above, we used method overriding, a technique that changes the method implementation defined in the base class without changing the method signature. This is essentially a method replacement, and it is the new method defined in the subclass that is called when the program runs.
Usually, when overriding a method, the @Override annotation is used, which tells the compiler to check the signatures of the overridden and overridden methods.
Read also:
Comments
Post a Comment