HTML Diff
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>