HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Слово "полиморфизм" в зависимости от контекста может означать разные вещи. Когда о полиморфизме говорят программисты на императивных языках, они, как правило, подразумевают "полиморфизм подтипов". В то же время программисты на функциональных языках имеют в виду "параметрический полиморфизм". О последнем и поговорим.</p>
1 <p>Слово "полиморфизм" в зависимости от контекста может означать разные вещи. Когда о полиморфизме говорят программисты на императивных языках, они, как правило, подразумевают "полиморфизм подтипов". В то же время программисты на функциональных языках имеют в виду "параметрический полиморфизм". О последнем и поговорим.</p>
2 <p><em>В этом уроке появляется код на TypeScript. Не переживайте, если не понимаете его до конца. Наша цель - разобраться с концепциями, а не с TypeScript.</em></p>
2 <p><em>В этом уроке появляется код на TypeScript. Не переживайте, если не понимаете его до конца. Наша цель - разобраться с концепциями, а не с TypeScript.</em></p>
3 <p>В библиотеке lodash есть функция _.concat(), которая объединяет переданные ей массивы:</p>
3 <p>В библиотеке lodash есть функция _.concat(), которая объединяет переданные ей массивы:</p>
4 <p>Эта функция объединяет любые массивы, независимо от типа данных, содержащихся внутри. Попробуем реализовать ее самостоятельно.</p>
4 <p>Эта функция объединяет любые массивы, независимо от типа данных, содержащихся внутри. Попробуем реализовать ее самостоятельно.</p>
5 <p>Посмотрите внимательно на этот код. Выполняются ли в нем какие-либо операции над данными внутри массива? Правильный ответ - нет. Эти данные перекладываются из одного массива в другой, но над ними не происходит никаких действий. Наша новая функция concat(), так же как и исходная _.concat(), может работать с массивами, содержащими любые типы данных.</p>
5 <p>Посмотрите внимательно на этот код. Выполняются ли в нем какие-либо операции над данными внутри массива? Правильный ответ - нет. Эти данные перекладываются из одного массива в другой, но над ними не происходит никаких действий. Наша новая функция concat(), так же как и исходная _.concat(), может работать с массивами, содержащими любые типы данных.</p>
6 <p>Для разработчиков, которые писали только на динамических языках, такое поведение кажется естественным, но в статических языках не все так просто.</p>
6 <p>Для разработчиков, которые писали только на динамических языках, такое поведение кажется естественным, но в статических языках не все так просто.</p>
7 <p>В TypeScript, при создании массива, задается тип элементов этого массива. Для первого это number, для второго string. Добавление в массив элемента другого типа приведет к ошибке:</p>
7 <p>В TypeScript, при создании массива, задается тип элементов этого массива. Для первого это number, для второго string. Добавление в массив элемента другого типа приведет к ошибке:</p>
8 <p>Функции, обрабатывающие массивы, ожидают определенный тип:</p>
8 <p>Функции, обрабатывающие массивы, ожидают определенный тип:</p>
9 <p>Обратите внимание на сигнатуру функции concat(): (arr1: number[], arr2: number[]): number[]. В отличие от варианта на JavaScript здесь указано, что входными параметрами являются массивы чисел number[]. То есть для массива строк эта функция работать не будет. Не будет она работать и для всех остальных типов данных.</p>
9 <p>Обратите внимание на сигнатуру функции concat(): (arr1: number[], arr2: number[]): number[]. В отличие от варианта на JavaScript здесь указано, что входными параметрами являются массивы чисел number[]. То есть для массива строк эта функция работать не будет. Не будет она работать и для всех остальных типов данных.</p>
10 <p>Что это означает на практике? Очень простую и печальную вещь. Нам придется реализовывать подобную функцию для<em>каждого типа</em>при том, что алгоритм внутри абсолютно идентичен.</p>
10 <p>Что это означает на практике? Очень простую и печальную вещь. Нам придется реализовывать подобную функцию для<em>каждого типа</em>при том, что алгоритм внутри абсолютно идентичен.</p>
11 <p>Именно тут нам пригодится параметрический полиморфизм. Статическим языкам приходится вводить в язык специальные конструкции, которые позволяют описывать подобные алгоритмы безотносительно типа параметра. В некоторых языках их называют шаблонами (C++) или дженериками (TypeScript, Java, C#):</p>
11 <p>Именно тут нам пригодится параметрический полиморфизм. Статическим языкам приходится вводить в язык специальные конструкции, которые позволяют описывать подобные алгоритмы безотносительно типа параметра. В некоторых языках их называют шаблонами (C++) или дженериками (TypeScript, Java, C#):</p>
12 <p>В этом коде появляется тип<em>T</em>, что как раз и означает возможность использования с любым типом внутри массива. Теперь метод concat() работает подобно аналогу из JavaScript.</p>
12 <p>В этом коде появляется тип<em>T</em>, что как раз и означает возможность использования с любым типом внутри массива. Теперь метод concat() работает подобно аналогу из JavaScript.</p>
13 <p>Параметрический полиморфизм дает возможность писать обобщенные алгоритмы для составных типов, что в некоторых случаях значительно сокращает количество кода. Иногда за это приходится платить сложностью решения, но для большинства типичных операций сложность растет не сильно. Это видно и по коду выше.</p>
13 <p>Параметрический полиморфизм дает возможность писать обобщенные алгоритмы для составных типов, что в некоторых случаях значительно сокращает количество кода. Иногда за это приходится платить сложностью решения, но для большинства типичных операций сложность растет не сильно. Это видно и по коду выше.</p>
14 <p>В динамических языках для реализации обобщенных алгоритмов параметрический полиморфизм не нужен. Любая коллекция может содержать любые типы данных в любой момент времени. Благодаря этому не требуется вводить дополнительные языковые конструкции и изучать новые концепции.</p>
14 <p>В динамических языках для реализации обобщенных алгоритмов параметрический полиморфизм не нужен. Любая коллекция может содержать любые типы данных в любой момент времени. Благодаря этому не требуется вводить дополнительные языковые конструкции и изучать новые концепции.</p>
15 <p>В литературе использование параметрического полиморфизма часто называется обобщенным программированием.</p>
15 <p>В литературе использование параметрического полиморфизма часто называется обобщенным программированием.</p>