- Что такое полиморфизм в ООП
- Польза полиморфизма в программировании
- Примеры полиморфизма в Python
- Проблемы полиморфизма подтипов в ООП
-
Пройди тест и узнай, какая сфера тебе подходит:
айти, дизайн или маркетинг.Бесплатно от Geekbrains
Что это такое? В объектно-ориентированном программировании полиморфизм является наследованием и его основным принципом. Звучит все сложно, но на самом деле не должно вызывать трудностей. Слово «полиморфизм» переводится как «много форм». Применив его к программированию, можно сказать, что любой код может иметь много разных форм.
Зачем нужен? Данный принцип нужен для облегчения работы программиста. Например, ему не придется писать каждый раз новый код, а достаточно скопировать свойства одного для создания другого похожего. К примеру: на сайте есть статьи, объявления и новости. Коды для их создания похожи, но не идентичны. Объединяет их основа – контент, а какой он, это уже допиленные коды. Более подробно про полиморфизм мы рассказали ниже в статье.
Что такое полиморфизм в ООП
Объектно-ориентированное программирование нередко требует создания новых классов, которые способны расширить структуру и поведение уже имеющегося класса. Это делается с использованием механизма наследования. Когда появляется новый класс, который расширяет старый, в его определении указывают, что он наследует от старого.
Новый содержит те же поля и классы, но в его теле указываются только новые (ранее не используемые) поля и методы. Возможность многократно использовать один и тот же код для создания новых делает процесс программирования более удобным, быстрым и простым.
Механизм наследования предполагает использование следующей терминологии. Когда класс D наследует от класса B, последний является базовым для D, а D — производным от B. Этот механизм в объектно-ориентированном программировании не только дает возможность брать фрагменты программ за основу производства новых, но и позволяет совершать одни и те же действия над объектами разных классов при помощи одних и тех же выражений. Это и есть «полиморфизм».
входят в ТОП-30 с доходом
от 210 000 ₽/мес
Скачивайте и используйте уже сегодня:
Топ-30 самых востребованных и высокооплачиваемых профессий 2023
Поможет разобраться в актуальной ситуации на рынке труда
Подборка 50+ бесплатных нейросетей для упрощения работы и увеличения заработка
Только проверенные нейросети с доступом из России и свободным использованием
ТОП-100 площадок для поиска работы от GeekBrains
Список проверенных ресурсов реальных вакансий с доходом от 210 000 ₽
Для того чтобы понять принцип полиморфизма, необходимо углубиться в теорию.
- Существуют абстрактные классы – это те, что содержат хотя бы один абстрактный метод (то есть требующий переопределения).
- Создать объект абстрактного класса нельзя.
- Производный класс имеет свойства и методы, унаследованные от базового, а также новые.
- Метод, который в производном классе переопределяется, имеет название «виртуальный». В базовом абстрактном классе информация о нем отсутствует.
- Абстрагирование заключается в определении метода в том месте, где имеются самые исчерпывающие данные о том, как он должен работать.
Чтобы дать определение полиморфизма, стоит рассмотреть пример его применения на практике. Существует информационный портал, на котором размещаются новости, объявления и разного рода статьи. Технически они имеют общие характеристики вроде заголовков и текста. Новости и объявления имеют дату публикации. Однако есть и отличия: статьи пишут конкретные авторы, новости берутся из определенных источников, объявления теряют актуальность спустя какое-то время.
Можно написать три отдельных класса для каждого рода публикаций и использовать тот, что нужен в данный момент. Но есть и другой вариант – сделать один класс со свойствами всех типов публикаций, при этом использоваться будут только нужные. Однако очевидно, что для разных типов аналогичные по принципу действия методы должны функционировать по-разному.
Абстрактный класс – это класс-шаблон. Он реализует функциональность только на том уровне, на котором она известна на данный момент. Производные же классы ее дополняют.
Польза полиморфизма в программировании
Полиморфизм является самым крупным бонусом от применения иерархических типов данных. Появляется возможность создавать более простой и обобщенный код с опорой на базовые типы, а благодаря этому повышать уровень абстракции и снижать сложность программы.
В данном случае под связыванием понимается сопоставление имени метода в коде с конкретной реализацией этого метода (адресом кода метода в памяти). Связывание на этапе компиляции называют статическим, на этапе выполнения – динамическим. Соответственно полиморфизм возможен только при динамическом связывании.
Рассмотрим типы полиморфизма без отсылки к объектно-ориентированному программированию, то есть в более широком смысле.
- Полиморфизм подтипов, или подтипизация (subtyping).
- Параметрический полиморфизм, применяется в обобщённом программировании.
- ad hoc полиморфизм, это перегрузка методов, основанная на той логике, что одинаковое имя метода может обозначать разные реализации в зависимости от своих параметров.
Примеры полиморфизма в Python
Посмотрим, как выражается полиморфизм. Примеры позволят понять принцип его действия.
Пример № 1. Существует оператор “+”, часто используемый в программах, которые созданы на Python. Однако его можно применять разными способами.
Скачать файлКогда речь идет о целочисленных типах данных, “+” используется для сложения операндов:
- number1 = 1
number2 = 2
print(number1 + number2)
В итоге программа покажет цифру 3.
При этом “+” можно применять и для конкатенации строк:
- string1 = «Hello,»
string2 = «Otus!»
print(string1+» «+string2)
Получаем ожидаемый результат «Hello, Otus!».
Это один из самых простых примеров полиморфизма на Python: мы имеем только один оператор “+”, который осуществляет разные операции для разных типов данных.
Читайте также!
Пример № 2. В «Пайтон» имеются функции, которые позволяют принимать аргументы различных типов – например, len().Рассмотрим подробнее, как это происходит.
- print(len(«ООП-программирование»))
print(len([«Python», «Java», «C#», «Scala», «C++»]))
print(len({«Где изучить?»: «В Otus», «Как проходят занятия?»: «Онлайн»}))
Получаем такой результат:
20
5
2
на курсы от GeekBrains до 24 ноября
Дело в том, что функция len() умеет взаимодействовать с разными типами данных: строкой, списком, кортежем, множеством, словарем. В приведенном примере одна и та же функция возвратила специфичную информацию для каждого типа данных, а именно:
- посчитала количество букв в слове «Программирование»;
- посчитала количество слов в списке;
- посчитала количество ключей в словаре.
Пример № 3. В Python, как и в остальных языках программирования, можно создавать классы, наследующие методы и атрибуты базового класса. Некоторые methods и attributes могут быть переопределены с целью их соответствия классу-потомку. Это называется переопределением (overriding). С помощью полиморфизма можно получать доступ к переопределенным методам и атрибутам с тем же именем, что и в родительском классе.
Рассмотрим пример переопределения такого рода.
from math import pi
class Shape:
def __init__(self, name):
self.name = name
def area(self):
pass
def fact(self):
return «Я — двумерная фигура»
def __str__(self):
return self.name
class Square(Shape):
def __init__(self, length):
super().__init__(«Квадрат»)
self.length = length
def area(self):
return self.length**2
def fact(self):
return «Любой угол квадрата равен 90 градусов.»
class Circle(Shape):
def __init__(self, radius):
super().__init__(«Круг»)
self.radius = radius
def area(self):
return pi*self.radius**2
a = Square(5)
b = Circle(8)
print(b)
print(b.fact())
print(a.fact())
print(b.area())
Смотрим на вывод программы:
- Круг
Я — двумерная фигура
Любой угол квадрата равняется 90 градусам.
201.06192982974676
Этот вариант полиморфизма работает следующим образом. В данном случае в работе кода были использованы методы __str__(), их не переопределили в дочерних классах, то есть они применяются прямо из родительского класса. Питоновский интерпретатор автоматически определил, что метод fact() для объекта a (class Square) является переопределенным. В итоге применяется тот метод, который был определен в классе-наследнике.
Метод fact() для объекта b не является переопределенным, поэтому используется метод с таким же именем из родительского класса (Shape).
Стоит сказать, что Python не поддерживает такой вариант переопределения метода как создание методов с таким же именем, но с различными типами аргументов.
Проблемы полиморфизма подтипов в ООП
Полиморфизм подтипов является одним из основных принципов объектно-ориентированного программирования, многие реализации которого базируются на неверном представлении о нем.
У ООП есть огромное количество недостатков, которые негативно влияют на всю отрасль в целом. И начинающие программисты должны их знать. К сожалению, объектно-ориентированное программирование, несмотря на свои неоспоримые недостатки, до сих пор является базой для вполне перспективных языков программирования.
Рассмотрим основные принципы ООП.
- Инкапсуляция. Независимость объектов, внутри каждого из которых находятся необходимые данные.
- Наследование. Возможность использовать один и тот же код так, что один объект может приобретать свойства другого.
- Полиморфизм подтипов. Свойство системы, благодаря которому объекты с одинаковым интерфейсом могут использоваться без информации их о типе и внутренней структуре.
Инкапсуляцию нельзя назвать уникальной для объектно-ориентированного программирования. Во многих языках она реализована в разных формах. Эти инструменты являются одними из самых полезных в любой библиотеке. Наследование также имеет достаточно широкое распространение вне ООП, но считается практически бесполезным. Сегодня программисты постепенно отказываются от его использования, сохраняя при этом нормальное функционирование кода.
Читайте также!
Единственным уникальным принципом объектно-ориентированного программирования является полиморфизм подтипов. Это одна из форм полиморфизма, которую многие считают удачной. Существует несколько альтернативных решений, например, интерфейсы, полиморфизм строк, параметрический полиморфизм и другие. Однако полиморфизм подтипов по-прежнему применяется даже в новых языках.
Кроме того, на практике подтипы имеют прочную связь с наследованием, несмотря на то, что обычно они упоминаются отдельно друг от друга. К примеру, чтобы создать подтип В от А, нужно наследовать его от А, как это представлено на картинке.
Кажется, что это ошибка, ведь существуют подтипы или другие формы полиморфизма, которые не наследуются. Помимо этого, осуществлять доступ к подтипам только через наследование в основном не слишком надежно.
Полиморфизм хорош тем, что позволяет создавать новые классы, логически очень похожие на базовые. Это обеспечивает возможность расширяемости и модифицируемости. В начале статьи мы привели простой пример, который продемонстрировал, как сильно облегчает разработку использование абстракций. То есть работать с новостями можно так же как с объявлениями или статьями.
Интересно, что нет необходимости узнавать, с каким именно объектом ведется работа. А если рассматривать не простой приведенный пример, а реальную работу более сложных приложений, польза полиморфизма становится еще более понятной.