JavaRush /Java Blog /Random EN /Why do we need polymorphism?
Павел
Level 11

Why do we need polymorphism?

Published in the Random EN group
Why are interfaces needed? Why do we need interface inheritance? Why do we need polymorphism? For those who read the definition of polymorphism and implemented several examples with interfaces, but did not understand why it is needed. There are bad habits, there are good ones, there are individual habits, and there are common ones. But no matter how common the habit is, each person does it with his own nuances. For example, my favorite habit is sleeping. All people sleep differently, and the Ivanov family also has a place to be. Why do we need polymorphism?  - 1Dad sleeps on his back and snores, and Mom sleeps on her right side and kicks. Let's move the sleepy realm to the world of Java. Knowing the meaning of interfaces, the sleep habit will be like this:
public interface ПривычкаСпать {
     String HowСпит();
}

public class Папа implements ПривычкаСпать {

    @Override
    public String HowСпит() {
        return "Папа спит на спине и похрапывает";
    }
}

public class Мама implements ПривычкаСпать {

    @Override
    public String HowСпит() {
        return "Мама спит на правом боку и пинается";
    }
}
In order to say exactly who is sleeping how, you need to go up to him and see who is sleeping here, and then we will be able to find out for sure whether we will hear snoring or get a kick with our foot. We will approach randomly, then to the Pope, then to the Mother. In the class with the main method , we will create a method that will randomly return to us either Dad or Mom .
public class Спальня {
    public static void main(String[] args) {

    }

    public static Object посмотретьКтоСпит() {
        int a = 1 + (int) (Math.random() * 2);
        if (a == 1) {
            return new Мама();
        }
        if (a == 2) {
            return new Папа();
        }
        return null;
    }
}
We do not know in advance who exactly will be returned by the seeWhoSleeps() method , so the type of the returned object will be common for all - Object . To check how the method works in main , we write a construction that will call the method being checked 10 times, and print the class of the resulting object:
for (int i = 0; i < 10; i++) {
    Object случайный = посмотретьКтоСпит ();
    System.out.println(случайный.getClass());
}
When launched, a random number of Moms and Dads will be displayed in the console.
class Dad class Dad class Mom class Dad class Dad class Mom class Mom class Mom class Dad class Mom
But back to sleep. We need to understand who sleeps how. Method to seeWhoSleeps () ; will return a random object, and write like this:
Object случайный = посмотретьКтоСпит ();
System.out.println(случайный.HowСпит());
We won't be able to. Because the variable random is of type Object , and Object doesn't have such a method, only Papa or Mama has it , but who's to stop that? Now let's cast the Object type to Dad or Mom , depending on the resulting class and the whole business. We write (you want switch, you want if, I chose if):
for (int i = 0; i < 10; i++) {
    Object случайный = посмотретьКтоСпит();

    if (случайный.getClass().equals(Мама.class)) {
        Мама мама = (Мама) случайный;
        System.out.println(мама. HowСпит());
    }
    if (случайный.getClass().equals(Папа.class)) {
        Папа папа = (Папа) случайный;
        System.out.println(папа. HowСпит());
    }
}
At the output, we will get an excellent result from sleeping Moms and Dads, the case is closed!
Dad sleeps on his back and snores Dad sleeps on his back and snores Mom sleeps on his right side and kicks Dad sleeps on his back and snores Dad sleeps on his back and snores Dad sleeps on his back and snores Dad sleeps on his back and snores Mom sleeps on his right side and kicks Dad sleeps on his back and snores Mom sleeps on his right side and kicks
And so it would be, if not for the ever-changing world. The Ivanov family has two more children, they also sleep in their own way, they need to be transferred to the Java world. And if the Petrovs come to visit the Ivanovs with their triplets, and they also sleep in their own way. As the program expands with new human classes that can sleep, the main method will turn into a Tower of Babel of a couple of hundred conditions.
for (int i = 0; i < 10; i++) {
    Object случайный = посмотретьКтоСпит();

    if (неизвестный.getClass().equals(Мама.class)) {
        Мама мама = (Мама) random;
        System.out.println(мама. HowСпит());
    }

    if (неизвестный.getClass().equals(Папа.class)) {
        Папа папа = (Папа) random;
        System.out.println(папа. HowСпит());
    }

//тут еще миллион строк codeа

}
That is, for expanding the program, such an organization of classes is not at all suitable. It forces us to write a lot of monotonous, mostly repetitive code. Only the father of all OOP, the brightest prince of flexibility - Polymorphism will help us. Why do we need polymorphism?  - 2Let's apply polymorphism and see what has changed:
public class Спальня {

public static void main(String[] args) {
	for (int i = 0; i < 10; i++) {
    	  ПривычкаСпать случайный = посмотретьКтоСпит ();
          System.out.println(случайный.HowСпит());
       }
}

public static ПривычкаСпать посмотретьКтоСпит() {
   //тут все без изменений
  }
}
In the lookWhoSleeps() method , the return type has changed, the Object class was common for all, the HabitSleep interface has become common only for Dad and Mom . This means that it is no longer necessary to explicitly change types from Object to Mom or Dad , and it is also no longer necessary to check the type of the incoming class. You can add at least +100500 people-classes who have a habit of sleeping, but the main methodwill be unchanged. Let's digress. Personally, I have an opinion that object-oriented programming is very much like writing texts. Nouns are more suitable for classes, verbs for methods, adjectives for class fields. For example, the sentence: "The red car is driving." can be rewritten in code:
public class Автомобиль {

String цвет = «Красный»;

public void ехать() {
 System.out.println(цвет + « автомобиль едет.»)
  }
}
You can also rewrite the code as a sentence, for example:
ПривычкаСпать случайный = посмотретьКтоСпит ();
System.out.println(случайный.HowСпит());
On a human it will be: "Display in the console how a random HabitSleep sleeps." Not too humanly, it was more correct to replace “The Habit of Sleeping” with “Man” . You can change the name of the interface HabitSleep to Person , then the logic will appear: there is a common Person and it has a method like Sleep() . But knowing about the problems with different habits from the last article about inheritance, it’s more correct to create the Person interface and inherit from the HabitSleep interface . And classes Dad and Mom implement the Human interface. Then everything will look logical: The sleep habit declares the method as sleeping
public interface ПривычкаСпать {
     String HowСпит();
}
The person also looks like a person with the habit of sleeping.
public interface Человек extends ПривычкаСпать {

}
Dad and Mom are people
public class Папа implements Человек {
    @Override
    public String HowСпит() {
        return "Папа спит на спине и похрапывает";
    }
}
public class Мама implements Человек {
    @Override
    public String HowСпит() {
        return "Мама спит на правом боку и пинается";
    }
}
And everything is fine in the main method too, the console displays "How a random person sleeps":
public class Спальня {

public static void main(String[] args) {
	for (int i = 0; i < 10; i++) {
    	  Человек случайный = посмотретьКтоСпит ();
          System.out.println(случайный.HowСпит());
       }
}

public static Человек посмотретьКтоСпит() {
   //тут все без изменений
  }
}
Dr. Bob Kelso summarizes for me. Why do we need polymorphism?  - 3Uncle Bob says: for a better understanding, rewrite the code in IDEA and run it. Polymorphism automatically defines a particular type of object with a common ancestor. We don't need to write checks for what type an object is. Summary for three articles: Here are the most obvious (for me) examples of using interfaces, inheritance and polymorphism. There are other worlds as well. In general, my main idea is: “An application is an implementation (abstraction) of the real world, and since the world is constantly changing, the application is constantly subject to change, you cannot write it once and for all. The process of making changes to an application can be long and incomprehensible or quick and understandable. It depends a lot on the organization of the code, on the organization of the classes, on the disciplined following of the rules.” The concepts of extensibility and change take the concept of programming to a new level. Perhaps, if we consider OOP through extensibility and making changes, we can quickly understand this very OOP. The next peaks after OOP will be: SOLID, clean code, application architecture and design patterns. They can also be understood in terms of extensibility and change.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION