Перейти к содержимому

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

  • автор:

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

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

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

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

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

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

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

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

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

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!" 

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

Полиморфизм для начинающих

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

Постановка задачи

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

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

Абстрактный класс

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

abstract class Publication
// таблица, в которой хранятся данные по элементу
protected $table ;

// свойства элемента нам неизвестны
protected $properties = array();

// конструктор
public function __construct ( $id )
// обратите внимание, мы не знаем, из какой таблицы нам нужно получить данные
$result = mysql_query ( ‘SELECT * FROM `’ . $this -> table . ‘` WHERE `id` #007700″>. $id . ‘» LIMIT 1’ );
// какие мы получили данные, мы тоже не знаем
$this -> properties = mysql_fetch_assoc ( $result );
>

// метод, одинаковый для любого типа публикаций, возвращает значение свойства
public function get_property ( $name )
if (isset( $this -> properties [ $name ]))
return $this -> properties [ $name ];

// метод, одинаковый для любого типа публикаций, устанавливает значение свойства
public function set_property ( $name , $value )
if (!isset( $this -> properties [ $name ]))
return false ;

$this -> properties [ $name ] = $value ;

// а этот метод должен напечатать публикацию, но мы не знаем, как именно это сделать, и потому объявляем его абстрактным
abstract public function do_print ();
>

Производные классы

Теперь можно перейти к созданию производных классов, которые и реализуют недостающую функциональность.

class News extends Publication
// конструктор класса новостей, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по новостям
$this -> table = ‘news_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘

‘ ;
echo $this -> properties [ ‘text’ ];
echo ‘
Источник: ‘ . $this -> properties [ ‘source’ ];
>
>

class Announcement extends Publication
// конструктор класса объявлений, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по объявлениям
$this -> table = ‘announcements_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘
Внимание! Объявление действительно до ‘ . $this -> properties [ ‘end_date’ ];
echo ‘

‘ . $this -> properties [ ‘text’ ];
>
>

class Article extends Publication
// конструктор класса статей, производного от класса публикаций
public function __construct ( $id )
// устанавливаем значение таблицы, в которой хранятся данные по статьям
$this -> table = ‘articles_table’ ;
// вызываем конструктор родительского класса
parent :: __construct ( $id );
>

// переопределяем абстрактный метод печати
public function do_print ()
echo $this -> properties [ ‘title’ ];
echo ‘

‘ ;
echo $this -> properties [ ‘text’ ];
echo ‘
© ‘ . $this -> properties [ ‘author’ ];
>
>

Теперь об использовании

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

// наполняем массив публикаций объектами, производными от Publication
$publications [] = new News ( $news_id );
$publications [] = new Announcement ( $announcement_id );
$publications [] = new Article ( $article_id );

foreach ( $publications as $publication ) // если мы работаем с наследниками Publication
if ( $publication instanceof Publication ) // то печатаем данные
$publication -> do_print ();
> else // исключение или обработка ошибки
>
>

Вот и все. Легким движением руки брюки превращаются в элегантные шорты :-).

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

Немного теории

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

Простыми словами о полиморфизме: 5‑я часть гайда по ООП

Объясняем сложную концепцию объектно-ориентированного программирования на примере интернет-магазина.

Иллюстрация: Катя Павловская для Skillbox Media

Максим Сафронов

Максим Сафронов

Автор, редактор, IT-журналист. Рассказывает о новых технологиях, цифровых профессиях и полезных инструментах для разработчиков. Любит играть на электрогитаре и программировать на Swift.

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

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

Все статьи про ООП
  • Что такое классы и объекты.
  • Особенности работы с объектами.
  • Модификаторы доступа, инкапсуляция.
  • Полиморфизм и перегрузка методов.
  • Полиморфизм.
  • Наследование и ещё немного полиморфизма.
  • Абстрактные классы и интерфейсы.
  • Практикум.

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

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

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

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

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

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

Допустим, мы делаем онлайн-магазин с мерчем известного ютуб-канала. У нас есть три вида товаров: футболки, кружки и блокноты. Задача — сделать так, чтобы все их можно было складывать в корзину и сайт каждый раз автоматически выдавал покупателю сообщение: «Товар такой-то добавлен в корзину». Как это сделать?

Есть два варианта. Можно писать свою версию метода «добавить в корзину» на каждую категорию товара — но это долго, да и код получится неопрятный. А можно написать один полиморфный метод, а потом использовать его для каждого нового объекта — и вот это как раз наш случай. Разберём весь процесс пошагово.

Шаг 1. Создаём базовый класс «Товар»

Базовый класс описывает общие свойства объектов. Например, у нас это название товара и возможность добавлять его в корзину.

public class Good // Объявляем класс «Товар» < public string name; // Указываем свойство «Название» // Создаём метод «Добавить в корзину» // Virtual означает, что метод потом можно будет дополнить под нужды конкретного товара. public virtual void AddToCart( ) < Console.WriteLine("Товар " + name + " добавлен в корзину"); > >

Пока всё это выглядит очень абстрактно, но дальше — больше.

Шаг 2. Создаём три производных класса: «Футболка», «Кружка» и «Блокнот»

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

public class Cup : Good // Создаём класс «Кружка» < public int volume; // Вводим дополнительное свойство «Объём» public override void AddToCart( ) // Override означает, что мы переопределяем метод AddToCart и добавляем ему новую функциональность < Console.WriteLine("Кружка " + name + " объёмом " + volume + " мл добавлена в корзину"); > > public class Note : Good // Создаём класс «Блокнот» < public int pages; // Добавляем свойство «Количество страниц» public override void AddToCart( ) < Console.WriteLine("Блокнот " + name + " на " + pages + " страниц добавлен в корзину"); > > public class Shirt : Good // Создаём класс «Футболка» < public int size; // Добавляем свойство «Размер» public override void AddToCart( ) < Console.WriteLine("Футболка " + name + " размером " + size + " добавлена в корзину"); > >

Шаг 3. Вызываем метод «Добавить в корзину»

Допустим, пользователь зашёл в наш магазин и решил купить три товара: футболку «Кислота» 48 размера, кружку «Омут» на 250 мл и блокнот «Древо жизни» на 180 страниц. Поставил он галочки напротив каждого товара, нажал «Добавить в корзину» — и вот какая история начинает происходить в коде:

using System; class Program < static void Main( ) < // Создаём объекты для каждого товара Shirt someShirt = new Shirt(); someShirt.name = "Кислота"; // Футболка «Кислота» someShirt.size = 48; Cup someCup = new Cup(); // Кружка «Омут» someCup.name = "Омут"; someCup.volume = 250; Note someNote = new Note(); someNote.name = "Древо жизни"; // Блокнот «Древо жизни» someNote.pages = 180; // Создаём массив из всех трёх объектов Good[] goods = new Good[3]; goods[0] = someShirt; goods[1] = someCup; goods[2] = someNote // С помощью цикла вызываем метод «Добавить в корзину» для каждого товара for(int i = 0; i < 3; i++) < goods[i].AddToCart(); >> >

Мы объединили товары в массив и с помощью цикла применили метод AddToCart сразу ко всем. Если бы наш магазин был реальным, пользователь получил бы примерно такие сообщения:

Футболка «Кислота размером» 48 добавлена в корзину Кружка «Омут» объёмом 250 мл добавлена в корзину Блокнот «Древо жизни» на 180 страниц добавлен в корзину

То есть мы достигли как раз того результата, который и планировали. Запустить код программы целиком и посмотреть, как он работает, можно по этой ссылке.

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

Смысл полиморфизма в том, что нам не надо писать для каждого товара свой метод — например, какой-нибудь AddToCartShirt для футболки или AddToCartCup для кружки. У нас просто есть один AddToCart, и мы на него полагаемся. Если в магазине появятся, например, кепки, мы просто немного допилим наш метод под особенности кепок, и дело в шляпе.

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

Отсюда можно выделить три главных преимущества полиморфизма:

  • Читаемость. Чем меньше кода и чем лучше он упакован, тем проще работать программистам и тем быстрее идёт разработка.
  • Масштабируемость. Можно добавить в магазин носки, ручки, напульсники, подвески и ещё кучу разных товаров, а за их покупку всё равно будет отвечать одна команда — AddToCart.
  • Предсказуемость кода. Когда у нас есть один метод для разных объектов, мы чувствуем себя спокойно. Можно не переживать, что команда «Добавить в корзину трусы» случайно применится к носкам и вызовет какой-то сбой в программе.

Что дальше

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

Читайте также:

  • Что такое объекты и классы: 1-я часть гайда по ООП
  • Тест: что ты знаешь о создателе Python Гвидо ван Россуме?
  • Как изучить Python самостоятельно и бесплатно

Полиморфизм (программирование)

Полиморфи́зм (от греч. πολὺ- — много, и μορφή — форма) в языках программирования — возможность объектов с одинаковой спецификацией иметь различную реализацию.

Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию — например, реализация класса может быть изменена в процессе наследования [1] .

Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс, множество реализаций».

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

  • внешняя общность проявляется как одинаковый набор методов с одинаковыми именами и сигнатурами (именами методов, типами аргументов и их количеством);
  • внутренняя общность — одинаковая функциональность методов. Её можно описать интуитивно или выразить в виде строгих законов, правил, которым должны подчиняться методы. Возможность приписывать разную функциональность одному методу (функции, операции) называется перегрузкой метода (перегрузкой функций, перегрузкой операций).

Примеры

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

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

В объектно-ориентированных языках

В объектно-ориентированных языках класс является абстрактным типом данных. [Прим. 1] Полиморфизм реализуется с помощью наследования классов и виртуальных функций. Класс-потомок наследует сигнатуры методов класса-родителя, а реализация, в результате переопределения метода, этих методов может быть другой, соответствующей специфике класса-потомка. Другие функции могут работать с объектом как с экземпляром класса-родителя, но если при этом объект на самом деле является экземпляром класса-потомка, то во время исполнения будет вызван метод, переопределенный в классе-потомке. Это называется поздним связыванием. [Примером использования может служить обработка массива, содержащего экземпляры как класса-родителя, так и класса-потомка: очевидно, что такой массив может быть объявлен только как массив типа класса-родителя и у объектов массива могут вызываться только методы этого класса, но если в классе-потомке какие-то методы были переопределены, то в режиме исполнения для экземпляров этого класса будут вызваны именно они, а не методы класса-родителя.]

Класс-потомок сам может быть родителем. Это позволяет строить сложные схемы наследования — древовидные или сетевидные.

Абстрактные (или чисто виртуальные) методы не имеют реализации вообще (на самом деле некоторые языки, например C++, допускают реализацию абстрактных методов в родительском классе). Они специально предназначены для наследования. Их реализация должна быть определена в классах-потомках.

Класс может наследовать функциональность от нескольких классов. Это называется множественным наследованием. Множественное наследование создаёт известную проблему (в C++), когда класс наследуется от нескольких классов-посредников, которые в свою очередь наследуются от одного класса (так называемая «Проблема ромба»): если метод общего предка был переопределён в посредниках, неизвестно, какую реализацию метода должен наследовать общий потомок. Решается эта проблема путём отказа от множественного наследования для классов и разрешением множественного наследования для полностью абстрактных классов (то есть интерфейсов) (C#, Delphi, Java), либо через виртуальное наследование (C++).

В функциональных языках

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

В Haskell существует два вида полиморфизма — параметрический (чистый) и специальный, (на основе классов [Прим. 2] ). Специальный называют еще ad hoc (от лат. ad hoc — специально). Их можно отличить следующим образом:

Параметрический полиморфизм

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

Специальный полиморфизм

Специальный (или лат. ad hoc ) полиморфизм допускает специальную реализацию для данных каждого типа. Например, используемая в нашем примере функцией сортировки функция сравнения должна быть определена по-разному для чисел, кортежей, списков, т. е. она является специально полиморфной. [источник не указан 931 день]

В Haskell есть деление на классы и экземпляры (instance), которого нет в ООП. Класс определяет набор и сигнатуры методов (возможно, задавая для некоторых или всех из них реализации по умолчанию), а экземпляры реализуют их. Таким образом, автоматически отпадает проблема множественного наследования. Классы не наследуют и не переопределяют методы других классов — каждый метод принадлежит только одному классу. Такой подход проще, чем сложная схема взаимоотношений классов в ООП. Некоторый тип данных может принадлежать нескольким классам; класс может требовать, чтобы каждый его тип обязательно принадлежал к другому классу, или даже нескольким; такое же требование может выдвигать экземпляр. Это аналоги множественного наследования. Есть и некоторые свойства, не имеющие аналогов в ООП. Например, реализация списка, как экземпляра класса сравнимых величин, требует, чтобы элементы списка также принадлежали к классу сравнимых величин.

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

Неявная типизация

В некоторых языках программирования (например, в Python и Ruby) применяется так называемая утиная типизация [2] (другие названия: латентная, неявная), которая представляет собой разновидность сигнатурного полиморфизма. Таким образом, например, в языке Python полиморфизм не обязательно связан с наследованием.

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

Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена.
Вы можете отредактировать эту статью, добавив ссылки на авторитетные источники.
Эта отметка установлена 12 мая 2011.

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

(упоминается в классической книге Саттера и Александреску, которая является источником).

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

В одном случае конкретный смысл фрагмента зависит от того, в каком окружении код был построен. Это т.н. статический полиморфизм. Перегрузка функций, шаблоны в Си++ реализуют именно статический полиморфизм. Если в коде шаблонного класса вызвана, например, std::sort, то реальный смысл вызова зависит от того, для каких именно типовых параметров будет развернут данный шаблон — вызовется одна из std::sort.

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

Полиморфизм включения

Этот полиморфизм называют чистым полиморфизмом. Применяя такую форму полиморфизма, родственные объекты можно использовать обобщенно. С помощью замещения и полиморфизма включения можно написать один метод для работы со всеми типами объектов TPerson. Используя полиморфизм включения и замещения можно работать с любым объектом, который проходит тест «is-A». Полиморфизм включения упрощает работу по добавлению к программе новых подтипов, так как не нужно добавлять конкретный метод для каждого нового типа, можно использовать уже существующий, только изменив в нем поведение системы. С помощью полиморфизма можно повторно использовать базовый класс; использовать любого потомка или методы, которые использует базовый класс.

Параметрический полиморфизм

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

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

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

Полиморфизм переопределения

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

Полиморфизм-перегрузка

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

Сравнение полиморфизма в функциональном и объектно-ориентированном программировании

Система классов в ФП и в ООП устроены по-разному, поэтому к их сравнению следует подходить очень осторожно.

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

Несмотря на концептуальные различия систем классов в ФП и ООП, реализуются они примерно одинаково — с помощью таблиц виртуальных методов.Используется часто в Java.

См. также

  • Перегрузка операций
  • Абстракция данных
  • Инкапсуляция (программирование)
  • Наследование (программирование)

Ссылки

  1. Почему формальную реляционную модель данных можно рассматривать как основу безимпедансных систем
  2. «Утиная типизация» (duck typing)

Примечания

  1. Не все так считают.
  2. Следует заметить, что класс в функциональных языках близок к интерфейсам в объектно-ориентированных языках.

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

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