Что такое полиморфизм в java
Перейти к содержимому

Что такое полиморфизм в java

Java Challengers #3: Полиморфизм и наследование

Мы продолжаем перевод серии статей с задачками по Java. Прошлый пост про строки вызвал на удивление бурную дискуссию. Надеемся, что мимо этой статьи вы тоже не пройдете мимо. И да — мы приглашаем теперь на юбилейный десятый поток нашего курса «Разработчик Java».

Согласно легендарному Венкату Субраманиам (Venkat Subramaniam) полиморфизм является самым важным понятием в объектно — ориентированном программировании. Полиморфизм — или способность объекта выполнять специализированные действия на основе его типа — это то, что делает Java — код гибким. Шаблоны проектирования, такие как Команда (Command), Наблюдатель (Observer), Декоратор (Decorator), Стратегия (Strategy), и многие другие, созданные бандой четырех (Gang Of Four), все используют ту или иную форму полиморфизма. Освоение этой концепции значительно улучшит вашу способность продумывать программные решения.

Вы можете взять исходный код для этой статьи и поэксперементировать здесь: https://github.com/rafadelnero/javaworld-challengers

Интерфейсы и наследование в полиморфизме

В этой статье мы сфокусируемся на связи между полиморфизмом и наследованием. Главное иметь в виду, что полиморфизм требует наследования или реализации интерфейса. Вы можете увидеть это на примере ниже с Дюком ( Duke ) и Джагги ( Juggy ):

public abstract class JavaMascot < public abstract void executeAction(); >public class Duke extends JavaMascot < @Override public void executeAction() < System.out.println("Punch!"); >> public class Juggy extends JavaMascot < @Override public void executeAction() < System.out.println("Fly!"); >> public class JavaMascotTest < public static void main(String. args) < JavaMascot dukeMascot = new Duke(); JavaMascot juggyMascot = new Juggy(); dukeMascot.executeAction(); juggyMascot.executeAction(); >>

Вывод этого кода будет таким:

Punch! Fly!

Так как определены конкретные реализации, то будут вызваны методы и Duke и Juggy .

Перегрузка (overloading) метода — это полиморфизм? Многие программисты путают отношение полиморфизма с переопределением методов (overriding) и перегрузкой методов (overloading). Фактически, только переопределение метода — это истинный полиморфизм. Перегрузка использует то же имя метода, но разные параметры. Полиморфизм — это широкий термин, поэтому всегда будут дискуссии на эту тему.

Какова цель полиморфизма

Большим преимуществом и целью использования полиморфизма является уменьшение связанности клиентского класса с реализацией. Вместо того чтобы хардкодить, клиентский класс получает реализацию зависимости для выполнения необходимого действия. Таким образом, клиентский класс знает минимум для выполнения своих действий, что является примером слабого связывания.

Чтобы лучше понять цель полиморфизма, взгляните на SweetCreator :

public abstract class SweetProducer < public abstract void produceSweet(); >public class CakeProducer extends SweetProducer < @Override public void produceSweet() < System.out.println("Cake produced"); >> public class ChocolateProducer extends SweetProducer < @Override public void produceSweet() < System.out.println("Chocolate produced"); >> public class CookieProducer extends SweetProducer < @Override public void produceSweet() < System.out.println("Cookie produced"); >> public class SweetCreator < private ListsweetProducer; public SweetCreator(List sweetProducer) < this.sweetProducer = sweetProducer; >public void createSweets() < sweetProducer.forEach(sweet ->sweet.produceSweet()); > > public class SweetCreatorTest < public static void main(String. args) < SweetCreator sweetCreator = new SweetCreator(Arrays.asList( new CakeProducer(), new ChocolateProducer(), new CookieProducer())); sweetCreator.createSweets(); >>

В этом примере вы можете видеть, что класс SweetCreator знает только о классе SweetProducer . Он не знает реализации каждого Sweet . Такое разделение дает нам гибкость для обновления и повторного использования наших классов, а это делает код намного проще в сопровождении. При проектировании кода всегда ищите способы сделать его максимально гибким и удобным. Полиморфизм — это очень мощный способ для использования в этих целях.

Аннотация @Override обязывает программиста использовать такую же сигнатуру метода, которая должна быть переопределена. Если метод не переопределен, будет ошибка компиляции.

Ковариантные возвращаемые типы при переопределении метода

Можно изменить тип возвращаемого значения переопределенного метода если это ковариантный тип. Ковариантный тип в основном является подклассом возвращаемого значения.

public abstract class JavaMascot < abstract JavaMascot getMascot(); >public class Duke extends JavaMascot < @Override Duke getMascot() < return new Duke(); >>

Поскольку Duke является JavaMascot , мы можем изменить тип возвращаемого значения при переопределении.

Полиморфизм в базовых классах Java

Мы постоянно используем полиморфизм в базовых классах Java. Один очень простой пример — создание экземпляра класса ArrayList с объявлением типа как интерфейс List .

List list = new ArrayList<>();

Рассмотрим пример кода, использующий Java Collections API без полиморфизма:

public class ListActionWithoutPolymorphism < // Пример без полиморфизма void executeVectorActions(Vectorvector) void executeArrayListActions(ArrayList arrayList) void executeLinkedListActions(LinkedList linkedList) void executeCopyOnWriteArrayListActions(CopyOnWriteArrayList copyOnWriteArrayList) < /* Здесь повтор кода */>> public class ListActionInvokerWithoutPolymorphism < listAction.executeVectorActions(new Vector<>()); listAction.executeArrayListActions(new ArrayList<>()); listAction.executeLinkedListActions(new LinkedList<>()); listAction.executeCopyOnWriteArrayListActions(new CopyOnWriteArrayList<>()); >

Отвратительный код, не так ли? Представьте себе, что вам нужно его сопровождать! Теперь рассмотрим тот же пример с полиморфизмом:

public static void main(String. polymorphism) < ListAction listAction = new ListAction(); listAction.executeListActions(); >public class ListAction < void executeListActions(Listlist) < // Выполнение действий с различными списками >> public class ListActionInvoker < public static void main(String. masterPolymorphism) < ListAction listAction = new ListAction(); listAction.executeListActions(new Vector<>()); listAction.executeListActions(new ArrayList<>()); listAction.executeListActions(new LinkedList<>()); listAction.executeListActions(new CopyOnWriteArrayList<>()); > >

Преимущество полиморфизма — гибкость и расширяемость. Вместо того чтобы создавать несколько различных методов, мы можем объявить один метод, который получает тип List .

Вызов конкретных методов для полиморфного метода

Можно вызвать конкретные методы при полиморфном вызове метода, это происходит за счет гибкости. Вот пример:

public abstract class MetalGearCharacter < abstract void useWeapon(String weapon); >public class BigBoss extends MetalGearCharacter < @Override void useWeapon(String weapon) < System.out.println("Big Boss is using a " + weapon); >void giveOrderToTheArmy(String orderMessage) < System.out.println(orderMessage); >> public class SolidSnake extends MetalGearCharacter < void useWeapon(String weapon) < System.out.println("Solid Snake is using a " + weapon); >> public class UseSpecificMethod < public static void executeActionWith(MetalGearCharacter metalGearCharacter) < metalGearCharacter.useWeapon("SOCOM"); // Следующая строка не будет работать // metalGearCharacter.giveOrderToTheArmy("Attack!"); if (metalGearCharacter instanceof BigBoss) < ((BigBoss) metalGearCharacter).giveOrderToTheArmy("Attack!"); >> public static void main(String. specificPolymorphismInvocation) < executeActionWith(new SolidSnake()); executeActionWith(new BigBoss()); >>

Техника, которую мы используем здесь — это приведение типов (casting) или сознательное изменение типа объекта во время выполнения.

Обратите внимание, что вызов определенного метода возможен только при приведении более общего типа к более специфичному типу. Хорошей аналогией было бы сказать явно компилятору: «Эй, я знаю, что я здесь делаю, поэтому я собираюсь привести объект к определенному типу и буду использовать этот метод.»

Ссылаясь на приведенный выше пример, у компилятора есть веская причина не принимать вызов определенных методов: класс, который передаётся должен быть SolidSnake . В этом случае, у компилятора нет никакого способа гарантировать, что каждый подкласс MetalGearCharacter имеет метод giveOrderToTheArmy .

Ключевое слово instanceof

Обратите внимание на зарезервированное слово instanceof . Перед вызовом конкретного метода мы спросили, является ли MetalGearCharacter экземпляром (instanceof) BigBoss . Если это не экземпляр BigBoss , мы получим следующее исключение:

Exception in thread `main" java.lang.ClassCastException: com.javaworld.javachallengers.polymorphism.specificinvocation.SolidSnake cannot be cast to com.javaworld.javachallengers.polymorphism.specificinvocation.BigBoss

Ключевое слово super

Что делать, если мы хотим сослаться на атрибут или метод из родительского класса? В этом случае мы можем использовать ключевое слово super .
Например:

public class JavaMascot < void executeAction() < System.out.println("The Java Mascot is about to execute an action!"); >> public class Duke extends JavaMascot < @Override void executeAction() < super.executeAction(); System.out.println("Duke is going to punch!"); >public static void main(String. superReservedWord) < new Duke().executeAction(); >>

Использование зарезервированного слова super в методе executeAction класса Duke вызывает метод родительского класса. Затем мы выполняем конкретное действие из класса Duke . Вот почему мы можем видеть оба сообщения в выводе:

The Java Mascot is about to execute an action! Duke is going to punch!

Решите задачку по полиморфизму

Давайте проверим, что вы узнали о полиморфизме и наследовании.

В этой задачке Вам дается несколько методов от Matt Groening’s The Simpsons, от вавам требуется разгадать, какой будет вывод для каждого класса. Для начала внимательно проанализируйте следующий код:

public class PolymorphismChallenge < static abstract class Simpson < void talk() < System.out.println("Simpson!"); >protected void prank(String prank) < System.out.println(prank); >> static class Bart extends Simpson < String prank; Bart(String prank) < this.prank = prank; >protected void talk() < System.out.println("Eat my shorts!"); >protected void prank() < super.prank(prank); System.out.println("Knock Homer down"); >> static class Lisa extends Simpson < void talk(String toMe) < System.out.println("I love Sax!"); >> public static void main(String. doYourBest) < new Lisa().talk("Sax :)"); Simpson simpson = new Bart("D'oh"); simpson.talk(); Lisa lisa = new Lisa(); lisa.talk(); ((Bart) simpson).prank(); >>

Как вы думаете? Каким будет результат? Не используйте IDE, чтобы выяснить это! Цель в том, чтобы улучшить ваши навыки анализа кода, поэтому постарайтесь решить самостоятельно.

Выберите ваш ответ (правильный ответ вы сможете найти в конце статьи).

A)
I love Sax!
D’oh
Simpson!
D’oh

B)
Sax 🙂
Eat my shorts!
I love Sax!
D’oh
Knock Homer down

C)
Sax 🙂
D’oh
Simpson!
Knock Homer down

D)
I love Sax!
Eat my shorts!
Simpson!
D’oh
Knock Homer down

Что случилось? Понимание полиморфизма

Для следующего вызова метода:

new Lisa().talk("Sax :)");

вывод будет «I love Sax!». Это потому, что мы передаём строку в метод и у класса Lisa есть такой метод.

Для следующего вызова:

Simpson simpson = new Bart("D'oh"); simpson.talk();

Вывод будет «Eat my shorts!». Это потому, что мы инициализируем тип Simpson с помощью Bart .

Теперь смотрите, это немного сложнее:

Lisa lisa = new Lisa(); lisa.talk();

Здесь мы используем перегрузку метода с наследованием. Мы ничего не передаем методу talk , поэтому вызывается метод talk из Simpson .

В этом случае на выходе будет «Simpson!».

((Bart) simpson).prank();

В этом случае строка prank была передана при создании экземпляра класса Bart через new Bart(«D’oh»); . В этом случае сначала вызывается метод super.prank() , а затем метод prank() из класса Bart . Вывод будет:

"D'oh" "Knock Homer down"

Распространенные ошибки с полиморфизмом

Распространенная ошибка думать, что можно вызвать конкретный метод без использования приведения типа.

Другой ошибкой является неуверенность в том, какой метод будет вызван при полиморфном создании экземпляра класса. Помните, что вызываемый метод является методом созданного экземпляра.

Также помните, что переопределение метода не является перегрузкой метода.

Невозможно переопределить метод, если параметры отличаются. Можно изменить тип возвращаемого значения переопределенного метода, если возвращаемый тип является подклассом.

Что нужно помнить о полиморфизме

  • Созданный экземпляр определяет, какой метод будет вызван при использовании полиморфизма.
  • Аннотация @Override обязывает программиста использовать переопределенный метод; в противном случае возникнет ошибка компилятора.
  • Полиморфизм может использоваться с обычными классами, абстрактными классами и интерфейсами.
  • Большинство шаблонов проектирования зависят от той или иной формы полиморфизма.
  • Единственный способ вызвать нужный ваш метод в полиморфном подклассе — это использовать приведение типов.
  • Можно создать мощную структуру кода, используя полиморфизм.
  • Экспериментируйте. Через это, вы сможете овладеть этой мощной концепцией!

Ответ

I love Sax! Eat my shorts! Simpson! D'oh Knock Homer down

Как всегда приветствую ваши комментарии и вопросы. И ждём у Виталия на открытом уроке.

Полиморфизм

Полиморфизм (polymorphism) — это понятие из объектно-ориентированного программирования, которое позволяет разным сущностям выполнять одни и те же действия. При этом неважно, как эти сущности устроены внутри и чем они различаются.

С греческого языка слово «полиморфизм» означает «многообразие». Термин используют и в других сферах. Скажем, полиморфизм в биологии — способность какого-то вида существовать в разных формах.

Пример полиформности в природе — пчелы: есть рабочие пчелы, матка, трутни. Они разные, но все могут летать независимо от того, что это за пчела. По похожему принципу работает и полиморфизм в ООП.

Освойте профессию
«Fullstack-разработчик на Python»

Профессия / 12 месяцев
Fullstack-разработчик на Python

Создавайте веб-проекты самостоятельно

dffsdd (3)

Fullstack-разработчик на Python

Fullstack-разработчики могут в одиночку сделать IT-проект от архитектуры до интерфейса. Их навыки востребованы у работодателей, особенно в стартапах. Научитесь программировать на Python и JavaScript и создавайте сервисы с нуля.

картинка - 2023-03-14T190323.524

Например, есть две разных сущности: картинка и видео. И тем, и другим можно поделиться: отправить в личное сообщение другому человеку. Программист может сделать два разных метода — один для картинки, другой для видео. А может воспользоваться полиморфизмом и создать один метод «Отправить» для обеих сущностей.

Такой метод будет называться полиморфным. Плюс этого подхода — разработчик пишет меньше кода и не повторяется.

Чтобы лучше понять, что такое полиморфизм и как он работает, советуем прочитать статью про ООП. Полиморфизм — один из четырех основных принципов этого способа программирования

Для чего нужен полиморфизм

  • Облегчает написание кода. Не нужно придумывать десять разных методов: отправить одно, другое, третье. Есть один метод, который можно применять к разным сущностям и не задумываться.
  • Позволяет масштабировать решения. Если понадобится отправлять не только видео и картинки, но и текст, это можно будет сделать той же командой.
  • Делает код более читаемым. Разработчику не нужно разбираться, что делает десяток методов с похожими названиями. Есть один метод, и по его названию все понятно.
  • Помогает точно понимать, чего ждать от разных методов, то есть делает код более предсказуемым. Не может быть такого, что метод «Отправить» вдруг окажется методом не для картинки, а для видео.

С понятием должен быть знаком любой разработчик. Множество языков программирования используют полиморфизм: C, C++, Java, Python и другие. Не все эти языки чисто объектно-ориентированные: некоторые устроены так, что с ними можно работать в разных парадигмах программирования. Так что столкнуться с полиморфизмом может каждый.

Станьте Fullstack-разработчик на Python и найдите стабильную работу
на удаленке

Полиморфизм как принцип ООП

В объектно-ориентированном программировании четыре основных принципа: инкапсуляция, абстракция, наследование и полиморфизм. Это связанные между собой вещи — без одного не работало бы и другое.

Инкапсуляция — это создание сущностей как «вещей в себе». Классы должны работать независимо друг от друга: если какая-то сущность, например, удалится, это не повлияет на принцип работы остальных.

Абстракция — это принцип, когда какие-то общие вещи сводятся до набора абстрактных признаков. То есть мы имеем не абсолютно разные классы «картинка», «видео», «текст», а абстрактный класс «контент».

Наследование — это возможность делать на основе одних сущностей другие. Обычно в качестве «родителя» используются абстрактные сущности, а от них наследуются уже более конкретные. То есть если родитель — «контент», то дети — «картинка», «видео», «текст». Это все подвиды контента и его наследники.

Чтобы реализовать полиморфизм, нужны как минимум абстракция и наследование. Они помогают сделать абстрактный класс, в нем — абстрактный «общий» метод, а потом унаследовать разные реализации этого метода. В итоге название одно, а механика разная в зависимости от подтипа. Сейчас разберемся подробнее.

Что такое полиморфный метод и как его создают

Полиформный — это многообразный: формы различаются, а действие одно и то же. Тот же самый метод «Отправить» из примера выше может быть реализован по-разному для видео и картинки. Но вызывается он одинаково для всех видов контента и выполняет одну и ту же задачу. Вот как это работает.

Сначала программист создает общий класс. Например, «контент». В нем он описывает вещи, общие для всего контента: свойства и методы. Свойства — это признаки, то, что есть у контента: количество лайков, возможность комментирования и так далее. А методы — это действия, то есть команды: контент можно лайкнуть, открыть на отдельной вкладке, репостнуть или отправить в личное сообщение.

У общего класса — абстрактные, общие методы. Контент можно отправить, но как — пока непонятно. Зато уже можно описать, как будет выглядеть эта команда: как она называется, что в нее нужно передать, какое сообщение выдать после этого. Это своего рода каркас будущего конкретного действия.

Затем разработчик создает производные классы. Это наследники общего класса: они более конкретные, у них могут быть дополнительные свойства и методы. Например, видео можно поставить на паузу, а картинку — нет. А еще у них сохраняются абстрактные свойства и методы родителя: их переопределяют, чтобы они тоже работали конкретнее.

У производных классов — свои реализации общих методов. Например, в классе «контент» есть метод «отправить». Он же есть и в производных классах. В классе «картинка» может быть свой код для отправки, а в классе «видео» — свой. Они могут быть похожи или различаться. Но название у них окажется одинаковым, и делать они будут одно и то же.

Можно создавать объекты производных классов и пользоваться их методами. Абстрактные классы существуют как бы в вакууме: нельзя создать объект, который будет принадлежать такому классу. Среди реальных объектов не может быть «просто контента», который не является ни текстом, ни картинкой, ни видео, ни еще чем-то. Соответственно, абстрактные методы никто не будет вызывать. А вот переопределенные методы из производных классов — вполне реальные, ими можно пользоваться в разных ситуациях.

Формы полиморфизма

Существуют разные виды полиморфизма. Вообще-то классификация довольно широкая и начинающему легко в ней запутаться, поэтому мы решили ограничиться только основными формами.

Полиморфизм подтипов. Это полиморфность «по умолчанию»: когда в ООП говорят о полиморфизме, обычно имеют в виду его. Выше мы рассказывали именно про такой тип. Это возможность использовать одни и те же команды, или интерфейсы, для разных сущностей — подтипов.

Параметрический полиморфизм. Его еще называют обобщенным полиморфизмом. В нем для команды не имеет значения, какую сущность ей прислали: для всех возможных классов будет использоваться один код. Такой полиморфизм считается «истинным» и делает код универсальнее, но реализовать его сложнее.

Полиморфизм ad hoc. Этот вид полиморфизма еще называют специализированным. Его иногда противопоставляют параметрическому: идея ad hoc — разный код при одинаковом названии. Часто такой полиморфизм реализуют с помощью перегрузки методов: несколько раз пишут метод с одним и тем же названием, но разным кодом.

Статический и динамический полиморфизм

На более «глубоком», близком к машине уровне полиморфизм можно разделить на две группы — статический и динамический. Разница —в том, когда программа переходит от общего метода к одной из его вариаций.

  • Статический — метод переопределяют при компиляции.
  • Динамический — при выполнении программы.

Статический полиморфизм реализуют с помощью перегрузки методов, о которой мы рассказывали выше. Динамический — с помощью абстракций. Обычно в объектно-ориентированных языках есть возможность применить оба варианта.

Преимущества полиморфизма

  • Код становится аккуратнее: не приходится множить сущности и создавать десяток команд, которые делают одно и то же. Нет «лапши» — бессвязного неструктурированного кода, в котором тяжело разобраться.
  • Разработчику удобнее: не нужно каждый раз думать, что делает команда «Отправить» для конкретного вида контента, можно просто написать ее и получить результат.
  • Работать с разными сущностями можно одинаково: не обязательно каждый раз узнавать, о каком именно производном классе речь идет на этот раз. Ведь общее полиморфное действие есть для всего.
  • Код легче расширять, использовать заново и всячески модифицировать.

Недостатки полиморфизма

  • Связь полиморфизма с наследованием порой расценивают как слабое место всей концепции. Если нужен полиформный класс, но для конкретной ситуации не подходит наследование, — реализация может усложниться.
  • Не всегда полиморфизм легко реализовать на практике. Поэтому существует довольно много реализаций, которые работают плохо: с багами и необъяснимыми ошибками.
  • Полиморфизм может ухудшать производительность кода, делать его более «тяжелым» и медленным. Но тут многое зависит от реализации: скажем, параметрический обычно быстрее, чем ad hoc.
  • Новичкам бывает тяжело понять принцип — объяснить полиморфизм простыми словами можно только в связке с другими понятиями ООП. Так что человек на момент изучения уже должен понимать, что такое объектно-ориентированное программирование.

Как начать изучать полиморфизм

Мы советуем начать с основ: сначала разобраться, как работает программирование в целом, потом перейти к принципам ООП и полиморфизму. На всех этапах лучше практиковаться, чтобы закреплять знания, — к тому же на реальных примерах легче понять тот или иной концепт.

Вы можете записаться на наши курсы и начать учиться уже сейчас. Обещаем много реальных задач и интересной практики!

Что такое полиморфизм в java

«Что нам даёт полиморфизм в Java? 1. Позволяет подменять реализации объектов. На этом основано тестирование.» Объясните пожалуйста этот пункт.

Акынбек Уровень 48 Expert
21 июня 2023
Почему-то почти перед каждым собеседованием приходится повторять основы ООП
Vitaly Demchenko Уровень 36
6 апреля 2023
Потрясающая статья! Спасибо, ребята, за труд!
25 декабря 2022
4 января 2022

Большое спасибо за статью! Хорошее, развернутое изложение. Также хороши поясняющие комментарии в коде. Затронуты смежные темы — суперполезно.

Marsel Aminov Уровень 30
29 декабря 2021
Четко и по полочкам, спасибо!
Barm Уровень 38
6 ноября 2021
24 января 2021
Всем привет! Спасибо автору за статью. )
4 октября 2020

Ещё важно отметить, что из-за того, что мы объявили слева переменную суперкласса, у созданного объекта будет доступен только функционал, написанный в предке. Если у наследника были ещё какие-то свои дополнительные методы и поля, они будут недоступны. Object obj = new StringBuilder(); Если мы попробуем у такого стрингбилдера вызвать метод аппенд, ничего не выйдет.

Что такое полиморфизм в Java?

Java — это язык объектно-ориентированного программирования (ООП), который особенно полезен, когда вам нужно реализовать хорошо структурированный код и повысить его повторное использование и ремонтопригодность. ООП использует четыре принципа для описания отношений между классами: наследование, инкапсуляция, абстракция и полиморфизм. В каждой Java-программе есть как минимум один класс. Поэтому очень важно понимать принципы ООП и то, как их использовать в своих приложениях. В этой статье рассматривается полиморфизм в его различных формах, как он соотносится с другими классами Java, а также варианты его использования и передовой опыт. Если у вас мало времени, воспользуйтесь приведенными ниже ссылками, чтобы найти именно то, что вы ищете:

Что такое полиморфизм в Java?

Полиморфизм, что буквально означает «разные формы», является одной из основных концепций ООП. Полиморфизм исследует, как создать и использовать два метода с одинаковыми именами для выполнения двух разных функций — например, добавить две функции с одинаковыми именами, но принимающие разные параметры. Например, давайте рассмотрим, как можно определить две функции с именем Multiply (). Один используется для вычисления произведения двух целых чисел, а другой — для вычисления произведения двух чисел типа double.
public class Main public static void main(String[] args) // using the first method
Multiplier.Multiply(3,5);
// using the second method
Multiplier.Multiply(3.5,5.1);
>
>

Когда код запущен, вывод выглядит следующим образом: Целочисленное умножение, результат = 15 двойное умножение, результат = 17,849999999999998 Вы заметите, что при вызове двух методов нет никакой разницы, кроме передаваемых параметров. Кроме того, обратите внимание, что выходные данные зависят от типа переданных параметров.

Различия между наследованием и полиморфизмом

Понятно, что разработчики иногда путают полиморфизм с другой ключевой концепцией ООП: наследованием. Однако эти два принципа существенно различаются. При наследовании класс, который называется дочерним классом, может наследовать методы и атрибуты другого класса (родительского класса). См. следующий пример:

class Shape // methods of Shape class
>
class Square extends Shape // methods of Shape class are not specified here but are automatically accessible to this Square class thanks to inheritance
// methods of Square class
>

При наследовании без полиморфизма дочерний класс наследует те же атрибуты и методы родительского класса без каких-либо модификаций их функциональности. При полиморфизме дочерний класс наследует атрибуты и методы, но предоставляет собственную реализацию (код) для этих методов. Наследование — это способ обеспечить возможность повторного использования кода, а полиморфизм — это способ динамического определения того, какая версия функции будет вызываться. Например, наследование позволяет использовать атрибуты и методы родительского класса. Напротив, полиморфизм позволяет дочернему классу определять свою версию функции с тем же именем, что и в родительском классе. В качестве альтернативы он позволяет реализовать функцию с одним и тем же именем несколькими различными способами и выбирает один из них для выполнения на основе количества и типов заданных параметров. Полиморфизм также используется для поддержки принципа «открыто-закрыто», который представляет собой букву «О» в аббревиатуре SOLID. В нем говорится, что код должен быть открыт для расширения и закрыт для модификации. Другими словами, когда вы пытаетесь добавить больше функциональности в свой код, вам не следует изменять существующие классы (закрытые для модификации). Вместо этого следует расширять функциональность за счет наследования и полиморфизма.

Полиморфизм против наследования: пример

Если у вас есть два типа автомобилей, например BMW и Mercedes, вы можете создать класс Car, а затем создать класс BMW и класс Mercedes, каждый из которых наследуется от класса Car. Это означает, что они наследуют его атрибуты и функции. При полиморфизме можно предположить, что Car (родительский класс) может быть BMW (дочерний класс) или Mercedes (дочерний класс). Следовательно, вы можете использовать родительский класс Car для ссылки на любой из двух типов автомобилей.
public class Car<>
Public class BMW extends Car <>
Public class Mercedes extends Car<>
Car myCar = new BMW();
//…some code…
myCar = new Mercedes();
//…some code…

В этом примере кода определяется переменная myCar типа Car и используется для хранения нового объекта — BMW. Затем он использовал ту же переменную для ссылки на Mercedes, что возможно, потому что они оба являются дочерними классами Car. Это простой пример повышения приведения, когда родительский класс ссылается на объект из дочернего класса. Используя восходящее преобразование, вы можете получить доступ к дочерней версии родительского класса. Это означает, что вы можете получить доступ к методам, которые были определены исключительно в родительском классе, но если метод с тем же именем указан в дочернем классе, вы можете получить доступ к этому. Восходящее преобразование полезно, когда вашему приложению необходимо определить, какую версию кода вызывать во время выполнения.

Типы и примеры полиморфизма в Java

  • Полиморфизм времени компиляции (статический полиморфизм)
  • Полиморфизм времени выполнения (динамический полиморфизм)

Полиморфизм времени компиляции

Этот тип полиморфизма, также называемый статическим полиморфизмом, достигается путем создания нескольких методов с одинаковыми именами в одном классе, но каждый из которых имеет разное количество параметров или параметров разных типов данных.

Обратите внимание, что в приведенном ниже примере три метода имеют одно и то же имя, но каждый из них принимает разное количество параметров или разные типы данных:

package com.hubspot;
class Multiplier static void Multiply(int a, int b)
System.out.println(«Integer Multiplication, Result double Multiplication, Result Three parameters, double Multiplication, Result ez-toc-section» > Полиморфизм времени выполнения

Этот тип полиморфизма, также называемый динамическим полиморфизмом, возникает, когда дочерний класс имеет собственное определение одного из методов-членов родительского класса. Это называется переопределением метода. В большинстве случаев полиморфизм среды выполнения связан с повышением приведения типов. Это когда родительский класс указывает на экземпляр дочернего класса.

Вот пример:
package com.hupspot;
// Super Class
class Shape protected double length;
Shape(double length) this.length = length;
>
void area() >
>
// Child class
class Square extends Shape //constructor
Square(double side) super(side); // calling the super class constructor
>
//Overriding area() method
void area() System.out.println(«Square Area Circle Area ez-toc-section» > Варианты использования полиморфизма и лучшие практики

Одним из вариантов использования полиморфизма является использование одного имени метода для автоматического вызова правильного метода в зависимости от класса. Например, при использовании одного элемента хранилища для хранения нескольких типов в следующем примере реализуется Set типа Shape из предыдущего примера и сохраняются объекты из разных дочерних классов, таких как Circle s и Square s:
Set hs = new HashSet();
hs.add(circle1);
hs.add(circle2);
hs.add(square1);
hs.add(square2);
for(Shape hs_element : hs) hs_element.area();
>
Другой пример использования полиморфизма — замена условных операторов в вашем коде. Например, в приведенном ниже коде используется оператор switch в методе области, чтобы определить, какой код запускать при его вызове, на основе первого переданного ему параметра. Вы заметите, что он достигает того же результата, что и приведенный выше пример кода полиморфизма времени выполнения. Однако этот подход не так прост.

package org.hubspot;
// Super Class
class Shape enum Type SQUARE,
CIRCLE
>
protected double length;
Type shape_type;
Shape(Type shape, double length) this.length = length;
this.shape_type = shape;
>
double area() double area = 0;
switch (shape_type)
case SQUARE:
area = length * length;
break;
case CIRCLE:
area = 3.14*length * length;
break;
>
return area;
>
>
public class Main public static void main(String[] args) Shape Circle = new Shape(Shape.Type.CIRCLE, 10);
System.out.println(«Circle Area equals Square Area equals ez-toc-section» > Использование полиморфизма в Java

Полиморфизм — удобный инструмент при разработке на Java или любом другом объектно-ориентированном языке. В этой статье объясняется, что такое полиморфизм в Java и как его использовать в ваших приложениях. Он показал примеры использования полиморфизма, такие как множитель, класс и различные вычисления площади для разных форм.

Мы также определили некоторые преимущества полиморфизма, такие как возможность повторного использования кода. Кроме того, он позволяет использовать единый интерфейс для обработки различных типов классов. Он также придерживается принципа SOLID ООП, расширяя классы вместо использования случая переключения. В результате приложение открыто для расширения и закрыто для модификации.

Наконец, полиморфизм очень полезен при разрешении методов, вызываемых либо во время выполнения, либо во время компиляции.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *