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

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

  • автор:

Полиморфизм

Полиморфизм в объектно-ориентированном программировании – это возможность обработки разных типов данных, т. е. принадлежащих к разным классам, с помощью «одной и той же» функции, или метода. На самом деле одинаковым является только имя метода, его исходный код зависит от класса. Кроме того, результаты работы одноименных методов могут существенно различаться. Поэтому в данном контексте под полиморфизмом понимается множество форм одного и того же слова – имени метода.

Например, два разных класса содержат метод total , однако инструкции каждого предусматривают совершенно разные операции. Так в примере ниже в классе T1 – это прибавление 10 к аргументу, в T2 – подсчет длины строки символов. В зависимости от того, к объекту какого класса применяется метод total , выполняются те или иные инструкции.

class T1: def __init__(self): self.n = 10 def total(self, a): return self.n + int(a) class T2: def __init__(self): self.string = 'Hi' def total(self, a): return len(self.string + str(a)) t1 = T1() t2 = T2() print(t1.total(35)) # Вывод: 45 print(t2.total(35)) # Вывод: 4

В предыдущем уроке мы уже наблюдали полиморфизм между классами, связанными наследованием. У каждого может быть свой метод __init__() или square() или какой-нибудь другой. Какой именно из методов square() вызывается, и что он делает, зависит от принадлежности объекта к тому или иному классу.

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

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

В Python среди прочего полиморфизм находит отражение в методах перегрузки операторов. Два из них мы уже рассмотрели. Это __init__ и __del__ , которые вызываются при создании объекта и его удалении. Полиморфизм у методов перегрузки операторов проявляется в том, что независимо от типа объекта, его участие в определенной операции, вызывает метод с конкретным именем. В случае __init__ операцией является создание объекта.

Рассмотрим пример полиморфизма на еще одном методе, который перегружает функцию str , которую автоматически вызывает функция print .

Если вы создадите объект собственного класса, а потом попробуете вывести его на экран, то получите информацию о классе объекта и его адрес в памяти. Такое поведение функции str() по-умолчанию по отношению к пользовательским классам запрограммировано на самом верхнем уровне иерархии, где-то в суперклассе, от которого неявно наследуются все остальные.

class A: def __init__(self, v1, v2): self.field1 = v1 self.field2 = v2 a = A(3, 4) b = str(a) print(a) print(b)

Здесь мы используем переменную b , чтобы показать, что функция print() вызывает str() неявным образом, так как вывод значений обоих переменных одинаков.

Если же мы хотим, чтобы, когда объект передается функции print() , выводилась какая-нибудь другая более полезная информация, то в класс надо добавить специальный метод __str__ . Этот метод должен обязательно возвращать строку, которую будет в свою очередь возвращать функция str() , вызываемая функций print() :

class A: def __init__(self, v1, v2): self.field1 = v1 self.field2 = v2 def __str__(self): s = str(self.field1)+" "+str(self.field2) return s a = A(3, 4) b = str(a) print(a) print(b)
3 4 3 4

Какую именно строку возвращает метод __str__() , дело десятое. Он вполне может строить квадратик из символов:

class Rectangle: def __init__(self, width, height, sign): self.w = int(width) self.h = int(height) self.s = str(sign) def __str__(self): rect = [] # количество строк for i in range(self.h): # знак повторяется w раз rect.append(self.s * self.w) # превращаем список в строку rect = '\n'.join(rect) return rect b = Rectangle(10, 3, '*') print(b)

Практическая работа. Метод перегрузки оператора сложения

В качестве практической работы попробуйте самостоятельно перегрузить оператор сложения. Для его перегрузки используется метод __add__ . Он вызывается, когда объекты класса, имеющего данный метод, фигурируют в операции сложения, причем с левой стороны. Это значит, что в выражении a + b у объекта a должен быть метод __add__ . Объект b может быть чем угодно, но чаще всего он бывает объектом того же класса. Объект b будет автоматически передаваться в метод __add__(self, b) в качестве второго аргумента.

Отметим, в Python также есть правосторонний метод перегрузки сложения – __radd__ .

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

Курс с примерами решений практических работ:
pdf-версия

X Скрыть Наверх

Объектно-ориентированное программирование на Python

Основные принципы ООП: полиморфизм в программировании

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

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

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

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

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

  1. Гибкость и расширяемость. Полиморфизм позволяет добавлять новые типы объектов и операций без изменения существующего кода. Новые классы, реализующие общий интерфейс, могут быть легко интегрированы в существующую систему.
  2. Упрощение кода. Полиморфизм способствует уменьшению дублирования кода. Общий интерфейс или абстрактный базовый класс позволяют описать общее поведение, и каждый конкретный класс реализует только свою специфичную логику.
  3. Читаемость кода. Полиморфизм делает код более интуитивно понимаемым, так как работа с различными объектами происходит через общий интерфейс. Это упрощает восприятие кода другими разработчиками и способствует поддержке программы.
  4. Расширение функциональности. Добавление новых функций или операций для существующих классов становится проще. Достаточно реализовать необходимые методы в новых классах, которые наследуют общий интерфейс.
  5. Повторное использование кода. Полиморфизм позволяет использовать одни и те же методы для разных типов данных. Это устраняет необходимость создания аналогичных функций для разных классов.
  6. Улучшение тестирования. Тестирование становится более удобным, так как можно создать общие тестовые сценарии для всех классов, реализующих один интерфейс. Это способствует повышению качества и надежности программы.
  7. Абстракция и инкапсуляция. Полиморфизм позволяет абстрагироваться от конкретных реализаций и сосредоточиться на общем поведении объектов. Также он способствует инкапсуляции, разделяя интерфейс от деталей реализации.
  8. Облегчение командной разработки. Когда разработчики работают над разными частями программы, полиморфизм позволяет им взаимодействовать через общие интерфейсы без необходимости глубокого понимания внутренней реализации друг друга.

Виды полиморфизма в объектно-ориентированном программировании

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

10 принципов ООП, о которых стоит знать каждому программисту

1. Полиморфизм подтипов (наследования)

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

class Shape: def area(self): pass class Circle(Shape): def __init__(self, radius): self.radius = radius def area(self): return 3.14159 * self.radius ** 2 class Rectangle(Shape): def __init__(self, width, height): self.width = width self.height = height def area(self): return self.width * self.height shapes = [Circle(5), Rectangle(4, 6)] for shape in shapes: print("Area:", shape.area()) 

2. Параметрический полиморфизм (обобщённое программирование)

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

def print_items(items): for item in items: print(item) numbers = [1, 2, 3] names = ["Alice", "Bob", "Charlie"] print_items(numbers) print_items(names) 

3. Полиморфизм в интерфейсах

Интерфейсный полиморфизм позволяет объектам разных классов реализовывать общий интерфейс и предоставлять схожее поведение без явного наследования.

from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def make_sound(self): pass class Dog(Animal): def make_sound(self): return "Woof!" class Cat(Animal): def make_sound(self): return "Meow!" def animal_sounds(animal): return animal.make_sound() dog = Dog() cat = Cat() print(animal_sounds(dog)) # Вывод: "Woof!" print(animal_sounds(cat)) # Вывод: "Meow!" 

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

Полиморфизм

Полиморфизм (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.
  • Новичкам бывает тяжело понять принцип — объяснить полиморфизм простыми словами можно только в связке с другими понятиями ООП. Так что человек на момент изучения уже должен понимать, что такое объектно-ориентированное программирование.

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

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

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

Полиморфизм: суть, проблемы применения

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

Зачем нужен? Данный принцип нужен для облегчения работы программиста. Например, ему не придется писать каждый раз новый код, а достаточно скопировать свойства одного для создания другого похожего. К примеру: на сайте есть статьи, объявления и новости. Коды для их создания похожи, но не идентичны. Объединяет их основа – контент, а какой он, это уже допиленные коды. Более подробно про полиморфизм мы рассказали ниже в статье.

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

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

Новый содержит те же поля и классы, но в его теле указываются только новые (ранее не используемые) поля и методы. Возможность многократно использовать один и тот же код для создания новых делает процесс программирования более удобным, быстрым и простым.

Механизм наследования предполагает использование следующей терминологии. Когда класс D наследует от класса B, последний является базовым для D, а D — производным от B. Этот механизм в объектно-ориентированном программировании не только дает возможность брать фрагменты программ за основу производства новых, но и позволяет совершать одни и те же действия над объектами разных классов при помощи одних и тех же выражений. Это и есть «полиморфизм».

Узнай, какие ИТ — профессии
входят в ТОП-30 с доходом
от 210 000 ₽/мес
Павел Симонов
Исполнительный директор Geekbrains

Команда GeekBrains совместно с международными специалистами по развитию карьеры подготовили материалы, которые помогут вам начать путь к профессии мечты.

Подборка содержит только самые востребованные и высокооплачиваемые специальности и направления в IT-сфере. 86% наших учеников с помощью данных материалов определились с карьерной целью на ближайшее будущее!

Скачивайте и используйте уже сегодня:

Павел Симонов - исполнительный директор Geekbrains

Павел Симонов
Исполнительный директор Geekbrains

Топ-30 самых востребованных и высокооплачиваемых профессий 2023

Поможет разобраться в актуальной ситуации на рынке труда

Подборка 50+ бесплатных нейросетей для упрощения работы и увеличения заработка

Только проверенные нейросети с доступом из России и свободным использованием

ТОП-100 площадок для поиска работы от GeekBrains

Список проверенных ресурсов реальных вакансий с доходом от 210 000 ₽

Получить подборку бесплатно
Уже скачали 26175

Для того чтобы понять принцип полиморфизма, необходимо углубиться в теорию.

  • Существуют абстрактные классы – это те, что содержат хотя бы один абстрактный метод (то есть требующий переопределения).
  • Создать объект абстрактного класса нельзя.
  • Производный класс имеет свойства и методы, унаследованные от базового, а также новые.
  • Метод, который в производном классе переопределяется, имеет название «виртуальный». В базовом абстрактном классе информация о нем отсутствует.
  • Абстрагирование заключается в определении метода в том месте, где имеются самые исчерпывающие данные о том, как он должен работать.

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

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

Написание одинаковых по сути методов для разных типов публикаций (get_news, get_announcements, get_articles) нельзя назвать правильным с точки зрения программирования. Именно здесь используется такое явление как полиморфизм.

Абстрактный класс – это класс-шаблон. Он реализует функциональность только на том уровне, на котором она известна на данный момент. Производные же классы ее дополняют.

Польза полиморфизма в программировании

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

Однако нет ясности, к какому именно конкретному типу в итоге будет относиться объект и как должны быть реализованы вызываемые методы. У компилятора не получится связать вызов метода с его реализацией.

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

Рассмотрим типы полиморфизма без отсылки к объектно-ориентированному программированию, то есть в более широком смысле.

  • Полиморфизм подтипов, или подтипизация (subtyping).
  • Параметрический полиморфизм, применяется в обобщённом программировании.
  • ad hoc полиморфизм, это перегрузка методов, основанная на той логике, что одинаковое имя метода может обозначать разные реализации в зависимости от своих параметров.

Примеры полиморфизма в Python

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

Пример № 1. Существует оператор “+”, часто используемый в программах, которые созданы на Python. Однако его можно применять разными способами.

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

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