0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Корректировка к слайду "Параметрический полиморфизм":</p>
1
<p>Корректировка к слайду "Параметрический полиморфизм":</p>
2
<p>--</p>
2
<p>--</p>
3
<p>В этом уроке мы поговорим немножко о терминах и о такой вещи, как полиморфизм.</p>
3
<p>В этом уроке мы поговорим немножко о терминах и о такой вещи, как полиморфизм.</p>
4
<h2>Что такое полиморфизм?</h2>
4
<h2>Что такое полиморфизм?</h2>
5
<p>В языках программирования и теории типов полиморфизмом называется способность функции обрабатывать данные разных типов.</p>
5
<p>В языках программирования и теории типов полиморфизмом называется способность функции обрабатывать данные разных типов.</p>
6
<h2>На практике</h2>
6
<h2>На практике</h2>
7
<p>Полиморфизм повышает коэффициент повторного использования кода, то есть уменьшает дублирование.</p>
7
<p>Полиморфизм повышает коэффициент повторного использования кода, то есть уменьшает дублирование.</p>
8
<h2>Виды полиморфизма</h2>
8
<h2>Виды полиморфизма</h2>
9
<ul><li>Ad-hoc (Специальный)</li>
9
<ul><li>Ad-hoc (Специальный)</li>
10
<li>Параметрический</li>
10
<li>Параметрический</li>
11
<li>Подтипов (включения)</li>
11
<li>Подтипов (включения)</li>
12
</ul><p>Со всеми примерами этих полиморфизмов мы уже встречались, но просто никогда не использовали эти термины.</p>
12
</ul><p>Со всеми примерами этих полиморфизмов мы уже встречались, но просто никогда не использовали эти термины.</p>
13
<h2>Параметрический полиморфизм</h2>
13
<h2>Параметрический полиморфизм</h2>
14
<p>Вызов ОДНОГО и того же кода для ВСЕХ допустимых типов (полиморфных) аргументов.</p>
14
<p>Вызов ОДНОГО и того же кода для ВСЕХ допустимых типов (полиморфных) аргументов.</p>
15
<p>Параметрический полиморфизм в теории типов и у людей, которые часто используют функциональные языки, обычно принято называть словом полиморфизм, что кстати говоря идёт в разрез с тем, что принято у программистов, которые пишут исключительно на объектно-ориентированных языках. Они под словом полиморфизм понимают полиморфизм подтипов.</p>
15
<p>Параметрический полиморфизм в теории типов и у людей, которые часто используют функциональные языки, обычно принято называть словом полиморфизм, что кстати говоря идёт в разрез с тем, что принято у программистов, которые пишут исключительно на объектно-ориентированных языках. Они под словом полиморфизм понимают полиморфизм подтипов.</p>
16
<p>Давайте представим ситуацию, с которой мы уже сталкивались. У нас есть список и мы вызываем операцию "собрать два списка в один":</p>
16
<p>Давайте представим ситуацию, с которой мы уже сталкивались. У нас есть список и мы вызываем операцию "собрать два списка в один":</p>
17
<p>append берет два списка и делает из них один.</p>
17
<p>append берет два списка и делает из них один.</p>
18
<p>Ещё один пример той же самой операции, но разница в том, что теперь здесь список строк:</p>
18
<p>Ещё один пример той же самой операции, но разница в том, что теперь здесь список строк:</p>
19
<p>Поскольку мы работаем в динамическом языке нам без разницы с какими типами работать. Какой бы список у нас не был и какой бы тип не содержался внутри какого-то основного типа - всё будет работать.</p>
19
<p>Поскольку мы работаем в динамическом языке нам без разницы с какими типами работать. Какой бы список у нас не был и какой бы тип не содержался внутри какого-то основного типа - всё будет работать.</p>
20
<p>В статических языках это совершенно не так и вы не можете просто так определить список чего угодно. У вас будет список конкретных структур, поэтому в таких языках нужны специальные механизмы, которые позволяют определять обобщённые списки.</p>
20
<p>В статических языках это совершенно не так и вы не можете просто так определить список чего угодно. У вас будет список конкретных структур, поэтому в таких языках нужны специальные механизмы, которые позволяют определять обобщённые списки.</p>
21
<p>Это важно по той простой причине, что применяя функцию append (операция объединения списков) можно увидеть, что над элементами, которые лежат в списке, никаких действий не производится вообще. Они не участвуют в этой операции и им не нужно это. То есть объединяя два списка мы не делаем никаких преобразований внутри. Соответственно, эта операция в общем случае не зависит от того, что хранится внутри.</p>
21
<p>Это важно по той простой причине, что применяя функцию append (операция объединения списков) можно увидеть, что над элементами, которые лежат в списке, никаких действий не производится вообще. Они не участвуют в этой операции и им не нужно это. То есть объединяя два списка мы не делаем никаких преобразований внутри. Соответственно, эта операция в общем случае не зависит от того, что хранится внутри.</p>
22
<p>Идеально - язык программирования должен позволять нам работать с этим именно так.</p>
22
<p>Идеально - язык программирования должен позволять нам работать с этим именно так.</p>
23
<p>Как мы уже говорили, в динамических языках мы получаем параметрический полиморфизм из коробки и действительно - функция append одна для любых списков, потому что мы не делаем здесь никаких различий, код будет один и его будет довольно мало.</p>
23
<p>Как мы уже говорили, в динамических языках мы получаем параметрический полиморфизм из коробки и действительно - функция append одна для любых списков, потому что мы не делаем здесь никаких различий, код будет один и его будет довольно мало.</p>
24
<p>В статических языках нет механизма для поддержки параметрического полиморфизма, им придётся писать функцию append для каждого типа. Представьте себе сколько может быть списков и сколько вообще может быть таких структур, для которых придётся так делать. По этой причине там существуют специальные механизмы. Особенно эти проблемы существуют в объектно-ориентированных языках, потому что в функциональных языках параметрический полиморфизм есть всегда и из коробки - это основа, а вот например, в таких языках как Java, существует специальный механизм, который называется<a>дженерики</a>. В C++ существует механизм, который называется<a>темплейты</a>.</p>
24
<p>В статических языках нет механизма для поддержки параметрического полиморфизма, им придётся писать функцию append для каждого типа. Представьте себе сколько может быть списков и сколько вообще может быть таких структур, для которых придётся так делать. По этой причине там существуют специальные механизмы. Особенно эти проблемы существуют в объектно-ориентированных языках, потому что в функциональных языках параметрический полиморфизм есть всегда и из коробки - это основа, а вот например, в таких языках как Java, существует специальный механизм, который называется<a>дженерики</a>. В C++ существует механизм, который называется<a>темплейты</a>.</p>
25
<p>В каких-то других языках это может называться по-другому, но всё это сводится к тому, чтобы иметь возможность пользоваться параметрическим полиморфизмом у себя в языке.</p>
25
<p>В каких-то других языках это может называться по-другому, но всё это сводится к тому, чтобы иметь возможность пользоваться параметрическим полиморфизмом у себя в языке.</p>
26
<h2>Ad-hoc полиморфизм</h2>
26
<h2>Ad-hoc полиморфизм</h2>
27
<p>Это самый простой тип полиморфизма. Он связан с тем, что в зависимости от типов аргументов применяется разная реализация какой-то операции.</p>
27
<p>Это самый простой тип полиморфизма. Он связан с тем, что в зависимости от типов аргументов применяется разная реализация какой-то операции.</p>
28
<p>Например, в данном случае сложения:</p>
28
<p>Например, в данном случае сложения:</p>
29
<p>Если у нас типы число и число, то у нас будет арифметическая операция. Если у нас две строчки, то это будет конкатенация. Если будут разные типы, то там уже зависит от ситуации.</p>
29
<p>Если у нас типы число и число, то у нас будет арифметическая операция. Если у нас две строчки, то это будет конкатенация. Если будут разные типы, то там уже зависит от ситуации.</p>
30
<p>Причём в статических языках, опять же, ad-hoc полиморфизм реализуется за счёт перегрузки функций (то есть описываются разные тела функций, в которых задаются разные типы аргументов) и соответственно компилятор сам выбирает какую функцию в какой момент использовать. Внутри нет никаких if’ов, то есть мы уже работаем конкретно с теми типами, которые мы определили в данной функции. Под одним именем одной операции скрывается несколько разных тел.</p>
30
<p>Причём в статических языках, опять же, ad-hoc полиморфизм реализуется за счёт перегрузки функций (то есть описываются разные тела функций, в которых задаются разные типы аргументов) и соответственно компилятор сам выбирает какую функцию в какой момент использовать. Внутри нет никаких if’ов, то есть мы уже работаем конкретно с теми типами, которые мы определили в данной функции. Под одним именем одной операции скрывается несколько разных тел.</p>
31
<p>В динамических языках мы этого делать не можем, поэтому там по сути всегда это сводится к тому, что у вас есть одна функция, внутри которой много if’ов, которые проверяют типы аргументов.</p>
31
<p>В динамических языках мы этого делать не можем, поэтому там по сути всегда это сводится к тому, что у вас есть одна функция, внутри которой много if’ов, которые проверяют типы аргументов.</p>
32
<p>Например, если посмотреть исходники console.log, можно увидеть, что там это примерно так и устроено. Там используется функция формат, которая внутри проверяет типы аргументов и в зависимости от типа делает какие-то разные действия.</p>
32
<p>Например, если посмотреть исходники console.log, можно увидеть, что там это примерно так и устроено. Там используется функция формат, которая внутри проверяет типы аргументов и в зависимости от типа делает какие-то разные действия.</p>
33
<h2>Полиморфизм подтипов</h2>
33
<h2>Полиморфизм подтипов</h2>
34
<p>Напомню, что полиморфизм подтипов в объектно-ориентированных языках называют просто полиморфизм, что не совсем корректно.</p>
34
<p>Напомню, что полиморфизм подтипов в объектно-ориентированных языках называют просто полиморфизм, что не совсем корректно.</p>
35
<p>Как раз этот полиморфизм позволяет вызывать РАЗНЫЙ код для РАЗНЫХ иерархий типов.</p>
35
<p>Как раз этот полиморфизм позволяет вызывать РАЗНЫЙ код для РАЗНЫХ иерархий типов.</p>
36
<p>Собственно, с этим полиморфизмом мы сквозь весь наш курс в первую очередь и знакомились и использовали его в нашей программе. И именно задача нашего курса была завести внутри языка полиморфизм подтипов.</p>
36
<p>Собственно, с этим полиморфизмом мы сквозь весь наш курс в первую очередь и знакомились и использовали его в нашей программе. И именно задача нашего курса была завести внутри языка полиморфизм подтипов.</p>
37
<p>Полиморфизм подтипов является ключевой штукой для ООП.</p>
37
<p>Полиморфизм подтипов является ключевой штукой для ООП.</p>
38
<p>Почему это нужно - мы уже прекрасно знаем. Бывает, что для разных типов нужно вызывать разную реализацию одних и тех же (с точки зрения интерфейса) функций для того, чтобы не писать if. Это как раз к вопросу о том, что эта штука исключительно просто сокращает код с точки зрения практики, а формально вы, конечно, можете работать и без него.</p>
38
<p>Почему это нужно - мы уже прекрасно знаем. Бывает, что для разных типов нужно вызывать разную реализацию одних и тех же (с точки зрения интерфейса) функций для того, чтобы не писать if. Это как раз к вопросу о том, что эта штука исключительно просто сокращает код с точки зрения практики, а формально вы, конечно, можете работать и без него.</p>
39
<h2>Итоги</h2>
39
<h2>Итоги</h2>
40
<p>Полиморфизм связан с динамической диспетчеризацией, которую мы разбирали. Просто динамическая диспетчеризация - это один из способов реализации полиморфизма.</p>
40
<p>Полиморфизм связан с динамической диспетчеризацией, которую мы разбирали. Просто динамическая диспетчеризация - это один из способов реализации полиморфизма.</p>
41
<p>Любой язык и любая штука, с которой мы работаем, позволяет нам использовать полиморфизм и как раз с помощью динамической диспетчеризации мы можем его, собственно, реализовать и таким образом просто сокращать тот код, который мы пишем.</p>
41
<p>Любой язык и любая штука, с которой мы работаем, позволяет нам использовать полиморфизм и как раз с помощью динамической диспетчеризации мы можем его, собственно, реализовать и таким образом просто сокращать тот код, который мы пишем.</p>