JavaRush /Java блог /Java Developer /Практика использования полиморфизма
Автор
Milan Vucic
Репетитор по программированию в Codementor.io

Практика использования полиморфизма

Статья из группы Java Developer
Привет! Сегодня мы заканчиваем серию лекций о принципах ООП. На этом занятии поговорим о полиморфизме. Практика использования полиморфизма - 1Полиморфизм — это возможность работать с несколькими типами так, будто это один и тот же тип. При этом поведение объектов будет разным в зависимости от того, к какому типу они принадлежат. Давай рассмотрим это утверждение подробнее. Начнем с первой части: «возможность работать с несколькими типами так, как будто это один и тот же тип». Как разные типы могут при этом быть одним и тем же? Звучит немного странно :/ На самом деле все просто. К примеру, такая ситуация возникает при обычном использовании наследования. Посмотрим, как это работает. Допустим, у нас есть простой родительский класс Cat с единственным методом run() — «бежать»:

public class Cat {

   public void run() {
       System.out.println("Бег!");
   }
}
А теперь создадим три класса, которые наследуются от Cat: Lion, Tiger и Cheetah, обозначающие льва, тигра и гепарда.

public class Lion extends Cat {

   @Override
   public void run() {
       System.out.println("Лев бежит со скоростью 80 км/ч");
   }
}

public class Tiger extends Cat {
  
   @Override
   public void run() {
       System.out.println("Тигр бежит со скоростью 60 км/ч");
   }
}

public class Cheetah extends Cat {

   @Override
   public void run() {
       System.out.println("Гепард бежит со скоростью до 120 км/ч");
   }
}
Итак, у нас есть 3 класса. Давай смоделируем ситуацию, при которой мы сможем работать с ними так, как будто это один и тот же класс. Представим, что кто-то из наших котов заболел, и ему нужна помощь доктора Айболита. Попробуем создать класс Aibolit, который будет способен лечить и львов, и тигров, и гепардов.

public class Aibolit {

   public void healLion(Lion lion) {

       System.out.println("Лев здоров!");
   }
  
   public void healTiger(Tiger tiger) {

       System.out.println("Тигр здоров!");
   }
  
   public void healCheetah(Cheetah cheetah) {

       System.out.println("Гепард здоров!");
   }
}
Казалось бы, проблема решена — класс написан и готов к работе. Но что мы будем делать, если захотим расширить нашу программу? Сейчас у нас всего 3 вида: львы, тигры, и гепарды. Но в мире существует больше 40 видов кошек. Представь, что будет, если мы добавим в программу отдельные классы для манулов, ягуаров, мейн-кунов, домашних кошек и всех остальных. Практика использования полиморфизма - 2Сама программа, конечно, будет функционировать, но вот в класс Aibolit придется постоянно добавлять новые методы для лечения каждого вида кошек, и в итоге он разрастется до невиданных размеров. Здесь и проявляется свойство полиморфизма — «возможность работать с несколькими типами так, как будто это один и тот же тип». Нам не нужно создавать бесчисленное количество методов, которые будут делать одно и то же — лечить кошку. Достаточно будет одного метода для всех случаев сразу:

public class Aibolit {

   public void healCat(Cat cat) {

       System.out.println("Пациент здоров!");
   }
}
В метод healCat() мы можем передавать и объекты Lion, и Tiger и Cheetah — они все являются Cat:

public class Main {

   public static void main(String[] args) {

       Aibolit aibolit = new Aibolit();

       Lion simba = new Lion();
       Tiger sherekhan = new Tiger();
       Cheetah chester = new Cheetah();

       aibolit.healCat(simba);
       aibolit.healCat(sherekhan);
       aibolit.healCat(chester);
   }
}
Вывод в консоль:

Пациент здоров!
Пациент здоров!
Пациент здоров!
Вот так наш класс Айболит может работать с разными типами, как будто это один и тот же тип. Теперь давай разберемся со второй частью: «при этом поведение объектов будет разным в зависимости от того, к какому типу они принадлежат». Здесь тоже все просто. В природе все кошки бегают по-разному. Как минимум, у них различается скорость бега. Среди наших трех питомцев гепард — самый быстрый, а тигр и лев бегают медленнее. То есть у них отличается поведение. Полиморфизм не только дает нам возможность использовать разные типы как один. Он при этом еще позволяет не забывать об их отличиях и сохраняет специфическое для каждого из них поведение. Это можно понять на таком примере. Допустим, после успешного выздоровления наши коты решили на радостях немного побегать. Добавим это в наш класс Aibolit:

public class Aibolit {

   public void healCat(Cat cat) {

       System.out.println("Пациент здоров!");
       cat.run();
   }
}
Попробуем выполнить тот же код для лечения трех зверей:

public static void main(String[] args) {

   Aibolit aibolit = new Aibolit();

   Lion simba = new Lion();
   Tiger sherekhan = new Tiger();
   Cheetah chester = new Cheetah();

   aibolit.healCat(simba);
   aibolit.healCat(sherekhan);
   aibolit.healCat(chester);
}
И вот как будет выглядеть результат:

Пациент здоров!
Лев бежит со скоростью 80 км/ч
Пациент здоров!
Тигр бежит со скоростью 60 км/ч
Пациент здоров!
Гепард бежит со скоростью до 120 км/ч
Здесь мы наглядно видим, что специфическое поведение наших объектов сохранилось, хотя мы передали всех троих зверей в метод, «обобщив» каждого из них до Cat. Благодаря полиморфизму Java прекрасно помнит, что это не просто три каких-то кота, а именно лев, тигр и гепард, которые бегают по-разному. В этом заключается главное преимущество использования полиморфизма — гибкость. Когда нам нужно создать какой-то общий для многих типов функционал — львы, тигры и гепарды превращаются просто в «котов». Все животные разные, но в некоторых ситуациях — кот есть кот, без разницы к какому виду он относится:) Вот тебе видеоподтверждение.
Когда же это «обобщение» не требуется, и нам наоборот нужно, чтобы поведение у видов отличалось, каждый тип ведет себя по-своему. Благодаря полиморфизму, ты создаешь единый интерфейс (набор методов) для широкого набора классов. За счет этого снижается сложность программ. Если бы мы даже расширили программу до 40 видов кошек, у нас все равно сохранился бы максимально простой интерфейс — один метод run() для всех 40 кошек.
Комментарии (139)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Роман Уровень 17
10 декабря 2023
Круто, спасибо! попробую сделать чтобы вмсто "пациент здоров" выводило "sherekhan здоров"
Anonymous #3361169 Уровень 47
1 декабря 2023
👍
Denis Gritsay Уровень 35
19 октября 2023
ИМХО главное тут это - возможность использования полиморфизма определяется иерархией наследования классов, объекты которых передаются в качестве аргументов. то есть передали Кэт один результат, Лион иной ....
Николай Уровень 20
14 сентября 2023
классная аналогия!
Петро Пумпинець Уровень 48 Expert
21 августа 2023
Nice article, relaxing video
chess.rekrut Уровень 25
21 августа 2023
easy
Alexander Rozenberg Уровень 32
25 июля 2023
fine
24 июля 2023
Благодаря этой лекции задумался: а не логичнее было бы называть классы с маленькой буквы, а обьекты с большой? Ведь в обычной жизни мы пишем "лев" с маленькой буквы, а "Симба" с большой а не наоборот
No Name Уровень 32
25 июня 2023
+ статья в копилке
Ислам Уровень 33
5 июня 2023
Nice