<!DOCTYPE html>
<html class="h-100" data-bs-theme="light" data-mantine-color-scheme="light" lang="ru" prefix="og: https://ogp.me/ns#">
<head>
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<link crossorigin="true" href="https://cdn.hexlet.io" rel="preconnect">
<link href="https://mc.yandex.ru" rel="preconnect">
<meta content="aa2vrdtq64dub8knuf83lwywit311w" name="facebook-domain-verification">
<link href="/favicon.ico" rel="icon" sizes="any">
<link href="/favicon.svg" rel="icon" type="image/svg+xml">
<link href="/apple-touch-icon.png" rel="apple-touch-icon">
<link href="/manifest.webmanifest" rel="manifest">
<script>
//<![CDATA[
window.gon={};gon.ym_counter="25559621";gon.is_bot=true;gon.applications={};gon.current_user={"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26 17:09:47 UTC","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false};gon.token="zVJ5Jg2jedLKNzwdc_ff6Gbeos5_OIiTFPSdjYSk2Twig7IR_93Usnx0GIV_-C-fptePZHcPdjGpFAfZ1qM-Ug";gon.locale="ru";gon.language="ru";gon.theme="light";gon.rails_env="production";gon.mobile=false;gon.google={"analytics_key":"UA-1360700-51","optimize_key":"GTM-5QDVFPF"};gon.captcha={"google_v3_site_key":"6LenGbgZAAAAAM7HbrDbn5JlizCSzPcS767c9vaY","yandex_site_key":"ysc1_Vyob5ZPPUdPBsu0ykt8bVFdzsfpoVjQChLGl2b4g19647a89","verification_failed":null};gon.social_signin=false;gon.typoreporter_google_form_id="1FAIpQLSeibfGq-KvWQ2Fyru-zkFFRVTLBuzXAHAoEyN1p49FtDmNoNA";
//]]>
</script>
<meta charset="utf-8">
<title>Полиморфизм | JS: Программирование, управляемое данными</title>
<meta name="description" content="Полиморфизм / JS: Программирование, управляемое данными: Познакомиться с понятием полиморфизма в языках программирования. Разобрать три типа полиморфизма.">
<link rel="canonical" href="https://ru.hexlet.io/courses/ddp/lessons/polymorphism/theory_unit">
<meta name="robots" content="noarchive">
<meta property="og:title" content="Полиморфизм">
<meta property="og:title" content="JS: Программирование, управляемое данными">
<meta property="og:description" content="Полиморфизм / JS: Программирование, управляемое данными: Познакомиться с понятием полиморфизма в языках программирования. Разобрать три типа полиморфизма.">
<meta property="og:url" content="https://ru.hexlet.io/courses/ddp/lessons/polymorphism/theory_unit">
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="O-RYnGJbXpQyGEV17JhaXldGsUpz79F_yfWDYbe_z1zUNZOrkCXz9IRbYe3gl6opl0-c4HvYL910FRk15bgoMg" />
<script src="/vite/assets/inertia-INZxX8jp.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/preload-helper-BJ4cLWpC.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ahoy-DrlRQ-1D.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/analytics-6pOtQ3OW.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Surface-DL2bpZA-.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/extends-C-EagtpE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/inheritsLoose-BBd-DCVI.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/objectWithoutPropertiesLoose-DRHXDhjp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/index.esm-DAqKOkZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Button-CGPUux8l.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/CloseButton-D1euiPao.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Group-BX48WcuU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Loader-BQEY8g6v.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Modal-Cy3HByv7.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/OptionalPortal-1Hza5P2w.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Stack-CtjJzfw4.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Textarea-Ck64llAy.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/DirectionProvider-Dc9zdUke.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/events-DJQOhap0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-reduced-motion-D2owz4wa.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-disclosure-zKtK5W1r.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/use-hotkeys-Cnc_Rwkb.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/random-id-DOQyszCZ.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/exports-C_MrNx_T.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<link rel="stylesheet" href="/vite/assets/application-BqhCP46M.js" />
<script src="/vite/assets/application-Df9RExpe.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/autocomplete-VMNbxKGl.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/createPopper-C3aM9r1M.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/js.cookie-D1-O8zkX.js" as="script" crossorigin="anonymous"><link rel="stylesheet" href="/vite/assets/application-C8HjmMaq.css" media="screen" />
<script>
window.ym = function(){(ym.a=ym.a||[]).push(arguments)};
window.addEventListener('load', function() {
setTimeout(function() {
ym.l = 1*new Date();
ym(window.gon.ym_counter, "init", {
clickmap: true,
trackLinks: true,
accurateTrackBounce: true,
webvisor: true
});
// Загружаем скрипт
var k = document.createElement('script');
k.async = 1;
k.src = 'https://mc.yandex.ru/metrika/tag.js';
document.head.appendChild(k);
ym(window.gon.ym_counter, 'getClientID', function(clientID) {
window.ymClientId = clientID;
});
}, 1500);
});
</script>
<!-- Google Tag Manager - deferred -->
<script>
// dataLayer stub сразу — пуши работают до загрузки скрипта
window.dataLayer = window.dataLayer || [];
// Сам скрипт — отложенно после load
window.addEventListener('load', function() {
setTimeout(function() {
dataLayer.push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var j = document.createElement('script');
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=GTM-WK88TH';
document.head.appendChild(j);
}, 1500);
});
</script>
<!-- End Google Tag Manager -->
</head>
<body>
<noscript>
<div>
<img alt="" src="https://mc.yandex.ru/watch/25559621" style="position:absolute; left:-9999px;">
</div>
</noscript>
<header class="sticky-top bg-body">
<nav class="navbar navbar-expand-lg">
<div class="container-xxl">
<a class="navbar-brand" href="/"><img alt="Логотип Хекслета" height="24" src="https://ru.hexlet.io/vite/assets/logo_ru_light-BpiEA1LT.svg" width="96">
</a><button aria-controls="collapsable" aria-expanded="false" aria-label="Меню" class="navbar-toggler border-0 mb-0 mt-1" data-bs-target="#collapsable" data-bs-toggle="collapse">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsable">
<ul class="navbar-nav mb-lg-0 mt-lg-1">
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
Все курсы
<span class="bi bi-chevron-down align-middle ms-1"></span>
</button>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item d-flex py-2" href="/courses"><div class="fw-bold me-auto">Все что есть</div>
<div class="text-muted">117</div>
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные категории</b>
</li>
<li>
<a class="dropdown-item py-2" href="/courses_devops">Курсы по DevOps
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_data_analytics">Курсы по аналитике данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_programming">Курсы по программированию
</a></li>
<li>
<a class="dropdown-item py-2" href="/courses_testing">Курсы по тестированию
</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li class="dropdown-item">
<b>Популярные курсы</b>
</li>
<li>
<a class="dropdown-item py-2" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/go">Go-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/java">Java-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/python">Python-разработчик
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/qa-auto-engineer-java">Автоматизатор тестирования на Java
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/data-analytics">Аналитик данных
</a></li>
<li>
<a class="dropdown-item py-2" href="/programs/frontend">Фронтенд-разработчик
</a></li>
</ul>
</li>
<li class="nav-item dropdown">
<button aria-haspopup class="btn nav-link" data-bs-toggle="dropdown" type="button">
О Хекслете
<span class="bi bi-chevron-down align-middle"></span>
</button>
<ul class="dropdown-menu bg-body">
<li>
<a class="dropdown-item py-2" href="/pages/about">О нас
</a></li>
<li>
<a class="dropdown-item py-2" href="/blog">Блог
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/hse-research" role="button">Результаты (Исследование)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://career.hexlet.io" role="button">Хекслет Карьера
</span></li>
<li>
<a class="dropdown-item py-2" href="/testimonials">Отзывы студентов
</a></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://t.me/hexlet_help_bot" role="button">Поддержка (В ТГ)
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/referal-program/?promo_creative=priglasite-druzei&promo_name=referal-program&promo_position=promo_position&promo_start=010724&promo_type=link" role="button">Реферальная программа
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://special.hexlet.io/certificate" role="button">Подарочные сертификаты
</span></li>
<li>
<span class="dropdown-item py-2 external-link" data-href="https://hh.ru/employer/4307094" role="button">Вакансии
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://b2b.hexlet.io" data-target="_blank" role="button">Компаниям
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexly.ru/" data-target="_blank" role="button">Колледж
</span></li>
<li>
<span class="dropdown-item d-flex external-link" rel="noopener noreferrer nofollow" data-href="https://hexlyschool.ru/" data-target="_blank" role="button">Частная школа
</span></li>
</ul>
</li>
<li><a class="nav-link" href="/subscription/new">Подписка</a></li>
</ul>
<ul class="navbar-nav flex-lg-row align-items-lg-center gap-2 ms-auto">
<li>
<a class="nav-link" aria-label="Переключить тему" href="/theme/switch?new_theme=dark"><span aria-hidden="true" class="bi bi-moon"></span>
</a></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="/u/new" role="button"><span>Регистрация</span>
</span></li>
<li>
<span data-target="_self" class="nav-link external-link" data-href="https://ru.hexlet.io/session/new" role="button"><span>Вход</span>
</span></li>
</ul>
</div>
</div>
</nav>
</header>
<div class="x-container-xxxl">
</div>
<main class="mb-6 min-vh-100 h-100">
<link rel="preload" as="image" href="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png"/><link rel="preload" as="image" href="/vite/assets/development-BVihs_d5.png"/><div id="app" data-page="{"component":"web/courses/lessons/theory_unit","props":{"errors":{},"locale":"ru","language":"ru","httpsHost":"https://ru.hexlet.io","host":"ru.hexlet.io","colorScheme":"light","auth":{"user":{"id":null,"last_viewed_notification_id":null,"email":null,"state":null,"first_name":"","last_name":"","created_at":"2026-02-26T17:09:47.786Z","current_program":null,"current_team":null,"full_name":"","guest":true,"can_use_paid_features":false,"is_hexlet_employee":false,"sanitized_phone_number":"","can_subscribe":true,"can_renew_education":false}},"cloudflareTurnstileSiteKey":"0x4AAAAAAA15KmeFXzd2H0Xo","vkIdClientId":"51586979","yandexIdClientId":"88d071f1d3384eb4bd1deb37910235c7","formAuthToken":"c2OXM4SfyvTBWDb8YltkiIri13b3r3Ghk99GvmS4262cslwEduFnlHcbEmRuVJT_Suv63P-YjwMuP9zqNr88ww","topics":[{"id":36819,"title":"Спасибо за такой прекрасный курс, было очень интересно!)","plain_title":"Спасибо за такой прекрасный курс, было очень интересно!) ","creator":{"public_name":"Cross Minder","id":153568,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":80488,"body":"Рад что понравилось)","topic_id":36819}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":13546,"title":"Скажите, есть ли недостатки у [такого решения](https://ru.hexlet.io/code_reviews/37510) и какие?","plain_title":"Скажите, есть ли недостатки у такого решения (https://ru.hexlet.io/code_reviews/37510) и какие? ","creator":{"public_name":"Виктор Журбин","id":161432,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":28442,"body":"У вас практически тоже самое. Главное замечение к этому коду `tag.attributes`, здесь нарушаются абстракции, потому что вместо обращения через интерфейсную функцию вы идете внутрь структуры.","topic_id":13546},{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":28443,"body":"Ну и линтер как обычно. Ошибок быть не должно.","topic_id":13546}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":17124,"title":"Имеет место на жизнь такое решение?\nhttps://ru.hexlet.io/code_reviews/56022","plain_title":"Имеет место на жизнь такое решение? https://ru.hexlet.io/code_reviews/56022 ","creator":{"public_name":"Александр Елахов","id":180236,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":36148,"body":"Имеет.","topic_id":17124}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":18442,"title":"Применения функции getAttribute найти не [удалось](https://ru.hexlet.io/code_reviews/62279?submission_id=85321).\n\nЭто же тоже диспетчеризация? Так можно?\n\nА, понял. Я полез в кишки абстракции `tags` и тем срезал путь. Нужно было через готовый интерфейс.","plain_title":"Применения функции getAttribute найти не удалось (https://ru.hexlet.io/code_reviews/62279?submission_id=85321). Это же тоже диспетчеризация? Так можно? А, понял. Я полез в кишки абстракции tags и тем срезал путь. Нужно было через готовый интерфейс. ","creator":{"public_name":"Roman Makarov","id":181967,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":38918,"body":"Добрый день, Роман! Вы уже разобрались?","topic_id":18442},{"creator":{"public_name":"Roman Makarov","id":181967,"is_tutor":false},"id":38947,"body":"Здравствуйте, Александр!\n\nДа, всё понятно, спасибо!","topic_id":18442}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":21216,"title":"Самостоятельно получилось решить только с if :(\n```\nДумаю, проблема была в том, что сразу не поняла, что идет жесткая привязка. Типа если tagName = img, то имя атрибута = 'src'. \nP.S. Это считается спойлером? На всякий случай спрятала. :D\n```","plain_title":"Самостоятельно получилось решить только с if :( Думаю, проблема была в том, что сразу не поняла, что идет жесткая привязка. Типа если tagName = img, то имя атрибута = 'src'. P.S. Это считается спойлером? На всякий случай спрятала. :D ","creator":{"public_name":"Сауле К","id":173341,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":45005,"body":"Спойлером не считается, так работает html.","topic_id":21216}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":34131,"title":"Подскажите.\nТег и имя атрибута я получаю правильные, если вывести их в консоль, но выпадает ошибка в выполнении функции getAttribute. \nhttps://ru.hexlet.io/code_reviews/169606","plain_title":"Подскажите. Тег и имя атрибута я получаю правильные, если вывести их в консоль, но выпадает ошибка в выполнении функции getAttribute. https://ru.hexlet.io/code_reviews/169606 ","creator":{"public_name":"Евгений Никитин","id":2478,"is_tutor":false},"comments":[{"creator":{"public_name":"Евгений Никитин","id":2478,"is_tutor":false},"id":74489,"body":"Разобрался.","topic_id":34131},{"creator":{"public_name":"Stanislav Dzisiak","id":212236,"is_tutor":true},"id":74509,"body":"**Евгений**, день добрый!\n\nЗдорово, что смогли разобраться!","topic_id":34131}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":43620,"title":"Здравствуйте! \nПосмотрите, пожалуйста: \nhttps://ru.hexlet.io/code_reviews/275732\n\nМне кажется, мое решение лучше учительского, т.к. в одном теге не могут быть одновременно и src, и href. Учительское решение слишком сложное для поставленной задачи, по времени у меня быстрее.","plain_title":"Здравствуйте! Посмотрите, пожалуйста: https://ru.hexlet.io/code_reviews/275732 Мне кажется, мое решение лучше учительского, т.к. в одном теге не могут быть одновременно и src, и href. Учительское решение слишком сложное для поставленной задачи, по времени у меня быстрее. ","creator":{"public_name":"Sofia","id":268513,"is_tutor":false},"comments":[{"creator":{"public_name":"Sofia","id":268513,"is_tutor":false},"id":94797,"body":"**Sofia**, правда вместо item надо было назвать tag","topic_id":43620},{"creator":{"public_name":"Sofia","id":268513,"is_tutor":false},"id":94942,"body":"**Сергей Мелодин**, ааааа, не обратила внимание это на условие, спасибо!","topic_id":43620},{"creator":{"public_name":"Sergei Melodyn","id":162475,"is_tutor":true},"id":94880,"body":"**Sofia**, приветствую.\n\nВаше решение нарушает требование задачи:\n> В коде не должно быть условных конструкций и, в целом, **любых логических выражений**. Используйте полиморфизм на основе ключей в объекте.\n\nОсновная идея - научиться полиморфизму, а не обхитрить решение учителя ;)","topic_id":43620}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":29667,"title":"Что делать, как решать, как использовать map, не понятно :(","plain_title":"Что делать, как решать, как использовать map, не понятно :( ","creator":{"public_name":"Artem Glushaev","id":176516,"is_tutor":false},"comments":[{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":64277,"body":"**Artem Glushaev**, если ничего не приходит в голову, как использовать map, то попробуйте решить любым другим удобным для вас способом, и если решение окажется не очень удачным, код потом всегда можно отрефакторить.\n\nЕсли хотите получить помощь, то надо по-взрослому оформить свой вопрос: https://help.hexlet.io/article/20-lessonquestion","topic_id":29667},{"creator":{"public_name":"Александр О.","id":61806,"is_tutor":false},"id":64301,"body":"**Artem Glushaev**,\n\n> Решено\n\nОтлично!","topic_id":29667},{"creator":{"public_name":"Artem Glushaev","id":176516,"is_tutor":false},"id":64292,"body":"Есть понимание, что я должен сделать какую-то таблицу, в которой буду хранить типы тэгов (link, a, img). Функция в map, должна сравнивать поступающий в нее тэг с типом из таблицы и если он совпадает, дергать аргумент (/foo). Сейчас я пытаюсь сделать такую функцию для одного тэга. И не могу понять, как достать имя тэга, чтобы его передать в getAttribute. Вот такие мысли сейчас есть, но не уверен, что они правильные. Если не использовать map и решать через логику (if), то у меня возникает такой же вопросом с именем тэга и с тем, как потом снова собрать список. ","topic_id":29667},{"creator":{"public_name":"Artem Glushaev","id":176516,"is_tutor":false},"id":64298,"body":"Решено","topic_id":29667},{"creator":{"public_name":"Dmitriy Bataev","id":106130,"is_tutor":false},"id":64266,"body":"Здравствуйте. С каким аспектом работы функции map связаны ваши проблемы? Возможно обсуждение механизма его работы вам поможет.","topic_id":29667}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":11598,"title":"Один из редких случаев, когда [решение](https://ru.hexlet.io/code_reviews/28660) почти как у учителя.\nПрямо приятно самому стало, что сам дошел до этого )))","plain_title":"Один из редких случаев, когда решение (https://ru.hexlet.io/code_reviews/28660) почти как у учителя. Прямо приятно самому стало, что сам дошел до этого ))) ","creator":{"public_name":"Азамат Абдуллин","id":155709,"is_tutor":false},"comments":[{"creator":{"public_name":"Kirill Mokevnin","id":1,"is_tutor":false},"id":24101,"body":"Только нужно поправить ошибки линтера, которых прямо полно.","topic_id":11598}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}},{"id":4968,"title":"Отличный курс, в какой то момент, думаю, даже соседи услышали громкий щелчок, когда у меня в голове многое на место встало.\nСпасибо!","plain_title":"Отличный курс, в какой то момент, думаю, даже соседи услышали громкий щелчок, когда у меня в голове многое на место встало. Спасибо! ","creator":{"public_name":"Александр Зотов","id":100726,"is_tutor":false},"comments":[{"creator":{"public_name":"Роман Лахтадыр","id":103858,"is_tutor":false},"id":8660,"body":"Отлично!","topic_id":4968}],"communitable":{"parent_entity_name":null,"parent_entity_url":null,"entity_name":"Полиморфизм","entity_url":null,"active":true}}],"lesson":{"exercise":{"id":639,"slug":"js_ddp_polymorphism_exercise","name":null,"state":"active","kind":"exercise","language":"javascript","locale":"ru","has_web_view":false,"has_test_view":false,"reviewable":true,"readme":"В HTML некоторые элементы хранят ссылку в атрибуте `href`, а некоторые — в `src`. Например:\n\n```html\n<img src=\"/logo.jpg\">\n<link href=\"/style.css\">\n<a href=\"/\">\n```\n\nАбстракция **Tags** содержит интерфейс для представления тега HTML:\n\n### Пример:\n\n```javascript\nconst hr = make('hr');\nconst a = make('a', { href: '/' });\n\ngetName(a); // a\ngetAttribute('href', a); // /\ngetAttribute('notexist', a); // undefined\n```\n\n* `make()` — принимает на вход два параметра: название тега и объект, в котором содержатся атрибуты и их значения.\n* `getName()` — принимает на вход тег, полученный вызовом `make()`, и возвращает его имя.\n* `getAttribute()` — принимает на вход имя атрибута и тег, полученный вызовом `make()`. Возвращает значение атрибута.\n\n## extract.js\n\nРеализуйте и экспортируйте по умолчанию функцию, которая принимает на вход _список_ тегов (только `<a>`, `<link>` и `<img>`) и возвращает список ссылок, извлеченных из этих тегов.\n\n### Пример:\n\n```javascript\nconst tags = l(\n make('a', { href: '/about' }),\n make('img', { src: '/avatar.jpeg' }),\n make('link', { href: '/favicon.ico' }),\n);\n\nextract(tags); // ('/about', '/avatar.jpeg', '/favicon.ico')\n```\n\n### Подсказки\n\n* Воспользуйтесь функцией `map()` для обхода коллекции.\n* В коде не должно быть условных конструкций и, в целом, любых логических выражений. Используйте полиморфизм на основе ключей в объекте.\n* Проанализируйте код файла `tags.js`, чтобы окончательно разобраться с устройством абстракции для тегов.\n* При необходимости вы можете самостоятельно импортировать функцию `toString()` из библиотеки `@hexlet/pairs-data` и использовать её для отладки решений.\n","prepared_readme":"В HTML некоторые элементы хранят ссылку в атрибуте `href`, а некоторые — в `src`. Например:\n\n```html\n<img src=\"/logo.jpg\">\n<link href=\"/style.css\">\n<a href=\"/\">\n```\n\nАбстракция **Tags** содержит интерфейс для представления тега HTML:\n\n### Пример:\n\n```javascript\nconst hr = make('hr');\nconst a = make('a', { href: '/' });\n\ngetName(a); // a\ngetAttribute('href', a); // /\ngetAttribute('notexist', a); // undefined\n```\n\n* `make()` — принимает на вход два параметра: название тега и объект, в котором содержатся атрибуты и их значения.\n* `getName()` — принимает на вход тег, полученный вызовом `make()`, и возвращает его имя.\n* `getAttribute()` — принимает на вход имя атрибута и тег, полученный вызовом `make()`. Возвращает значение атрибута.\n\n## extract.js\n\nРеализуйте и экспортируйте по умолчанию функцию, которая принимает на вход _список_ тегов (только `<a>`, `<link>` и `<img>`) и возвращает список ссылок, извлеченных из этих тегов.\n\n### Пример:\n\n```javascript\nconst tags = l(\n make('a', { href: '/about' }),\n make('img', { src: '/avatar.jpeg' }),\n make('link', { href: '/favicon.ico' }),\n);\n\nextract(tags); // ('/about', '/avatar.jpeg', '/favicon.ico')\n```\n\n### Подсказки\n\n* Воспользуйтесь функцией `map()` для обхода коллекции.\n* В коде не должно быть условных конструкций и, в целом, любых логических выражений. Используйте полиморфизм на основе ключей в объекте.\n* Проанализируйте код файла `tags.js`, чтобы окончательно разобраться с устройством абстракции для тегов.\n* При необходимости вы можете самостоятельно импортировать функцию `toString()` из библиотеки `@hexlet/pairs-data` и использовать её для отладки решений.\n","has_solution":true,"entity_name":"Полиморфизм"},"units":[{"id":1399,"name":"theory","url":"/courses/ddp/lessons/polymorphism/theory_unit"},{"id":1608,"name":"quiz","url":"/courses/ddp/lessons/polymorphism/quiz_unit"},{"id":2022,"name":"exercise","url":"/courses/ddp/lessons/polymorphism/exercise_unit"}],"links":[],"ordered_units":[{"id":1399,"name":"theory","url":"/courses/ddp/lessons/polymorphism/theory_unit"},{"id":1608,"name":"quiz","url":"/courses/ddp/lessons/polymorphism/quiz_unit"},{"id":2022,"name":"exercise","url":"/courses/ddp/lessons/polymorphism/exercise_unit"}],"id":706,"slug":"polymorphism","state":"approved","name":"Полиморфизм","course_order":900,"goal":"Познакомиться с понятием полиморфизма в языках программирования. Разобрать три типа полиморфизма.","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"172395950","theory":"Корректировка к слайду «Параметрический полиморфизм»:\n\n```javascript\nappend(numbers1, numbers2)\n```\n\n```javascript\nappend(strings1, strings2)\n```\n\n--\n\nВ этом уроке мы поговорим немножко о терминах и о такой вещи, как полиморфизм.\n\n## Что такое полиморфизм?\n\n```\nВ языках программирования и теории типов полиморфизмом\nназывается способность функции обрабатывать данные разных типов.\n```\n\n## На практике\n\n```\nПолиморфизм повышает коэффициент повторного использования кода,\nто есть уменьшает дублирование.\n```\n\n## Виды полиморфизма\n\n- Ad-hoc (Специальный)\n- Параметрический\n- Подтипов (включения)\n\nСо всеми примерами этих полиморфизмов мы уже встречались, но просто никогда не использовали эти термины.\n\n## Параметрический полиморфизм\n\n```\nВызов ОДНОГО и того же кода для ВСЕХ\nдопустимых типов (полиморфных) аргументов.\n```\n\nПараметрический полиморфизм в теории типов и у людей, которые часто используют функциональные языки, обычно принято называть словом полиморфизм, что кстати говоря идёт в разрез с тем, что принято у программистов, которые пишут исключительно на объектно-ориентированных языках. Они под словом полиморфизм понимают полиморфизм подтипов.\n\nДавайте представим ситуацию, с которой мы уже сталкивались. У нас есть список и мы вызываем операцию «собрать два списка в один»:\n\n```javascript\nconst numbers1 = l(3, 4, 5, 8)\nconst numbers2 = l(3, 2, 9)\nappend(numbers1, numbers2) // (3, 4, 5, 8, 2, 9)\n```\n\n`append` берет два списка и делает из них один.\n\nЕщё один пример той же самой операции, но разница в том, что теперь здесь список строк:\n\n```javascript\nconst strings1 = l('cat', 'dog')\nconst strings2 = l('table', 'milk', 'phone')\nappend(strings1, strings2) // (cat, dog, table, milk, phone)\n```\n\nПоскольку мы работаем в динамическом языке нам без разницы с какими типами работать. Какой бы список у нас не был и какой бы тип не содержался внутри какого-то основного типа – всё будет работать.\n\nВ статических языках это совершенно не так и вы не можете просто так определить список чего угодно. У вас будет список конкретных структур, поэтому в таких языках нужны специальные механизмы, которые позволяют определять обобщённые списки.\n\nЭто важно по той простой причине, что применяя функцию `append` (операция объединения списков) можно увидеть, что над элементами, которые лежат в списке, никаких действий не производится вообще. Они не участвуют в этой операции и им не нужно это. То есть объединяя два списка мы не делаем никаких преобразований внутри. Соответственно, эта операция в общем случае не зависит от того, что хранится внутри.\n\nИдеально – язык программирования должен позволять нам работать с этим именно так.\n\nКак мы уже говорили, в динамических языках мы получаем параметрический полиморфизм из коробки и действительно – функция `append` одна для любых списков, потому что мы не делаем здесь никаких различий, код будет один и его будет довольно мало.\n\nВ статических языках нет механизма для поддержки параметрического полиморфизма, им придётся писать функцию `append` для каждого типа. Представьте себе сколько может быть списков и сколько вообще может быть таких структур, для которых придётся так делать. По этой причине там существуют специальные механизмы.\nОсобенно эти проблемы существуют в объектно-ориентированных языках, потому что в функциональных языках параметрический полиморфизм есть всегда и из коробки – это основа, а вот например, в таких языках как Java, существует специальный механизм, который называется [дженерики](https://en.wikipedia.org/wiki/Generics_in_Java). В C++ существует механизм, который называется [темплейты](https://ru.wikipedia.org/wiki/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B_C++).\n\nВ каких-то других языках это может называться по-другому, но всё это сводится к тому, чтобы иметь возможность пользоваться параметрическим полиморфизмом у себя в языке.\n\n## Ad-hoc полиморфизм\n\nЭто самый простой тип полиморфизма. Он связан с тем, что в зависимости от типов аргументов применяется разная реализация какой-то операции.\n\nНапример, в данном случае сложения:\n\n```javascript\n1 + 1 // 2\n'cat' + 'dog' // catdog\n\nconsole.log(1034.98) // => 1034.98\nconsole.log('hello') // => hello\n```\n\nЕсли у нас типы число и число, то у нас будет арифметическая операция. Если у нас две строчки, то это будет конкатенация. Если будут разные типы, то там уже зависит от ситуации.\n\nПричём в статических языках, опять же, ad-hoc полиморфизм реализуется за счёт перегрузки функций (то есть описываются разные тела функций, в которых задаются разные типы аргументов) и соответственно компилятор сам выбирает какую функцию в какой момент использовать. Внутри нет никаких if’ов, то есть мы уже работаем конкретно с теми типами, которые мы определили в данной функции. Под одним именем одной операции скрывается несколько разных тел.\n\nВ динамических языках мы этого делать не можем, поэтому там по сути всегда это сводится к тому, что у вас есть одна функция, внутри которой много if’ов, которые проверяют типы аргументов.\n\nНапример, если посмотреть исходники `console.log`, можно увидеть, что там это примерно так и устроено. Там используется функция формат, которая внутри проверяет типы аргументов и в зависимости от типа делает какие-то разные действия.\n\n## Полиморфизм подтипов\n\nНапомню, что полиморфизм подтипов в объектно-ориентированных языках называют просто полиморфизм, что не совсем корректно.\n\nКак раз этот полиморфизм позволяет вызывать РАЗНЫЙ код для РАЗНЫХ иерархий типов.\n\n```javascript\nconst obj = new SimpleCard() // or PercentCard()\nobj.damage(health)\n```\n\nСобственно, с этим полиморфизмом мы сквозь весь наш курс в первую очередь и знакомились и использовали его в нашей программе. И именно задача нашего курса была завести внутри языка полиморфизм подтипов.\n\nПолиморфизм подтипов является ключевой штукой для ООП.\n\nПочему это нужно – мы уже прекрасно знаем. Бывает, что для разных типов нужно вызывать разную реализацию одних и тех же (с точки зрения интерфейса) функций для того, чтобы не писать `if`.\nЭто как раз к вопросу о том, что эта штука исключительно просто сокращает код с точки зрения практики, а формально вы, конечно, можете работать и без него.\n\n## Итоги\n\nПолиморфизм связан с динамической диспетчеризацией, которую мы разбирали. Просто динамическая диспетчеризация – это один из способов реализации полиморфизма.\n\nЛюбой язык и любая штука, с которой мы работаем, позволяет нам использовать полиморфизм и как раз с помощью динамической диспетчеризации мы можем его, собственно, реализовать и таким образом просто сокращать тот код, который мы пишем.\n"},"lessonMember":null,"courseMember":null,"course":{"start_lesson":{"exercise":null,"units":[{"id":1378,"name":"theory","url":"/courses/ddp/lessons/intro/theory_unit"}],"links":[],"ordered_units":[{"id":1378,"name":"theory","url":"/courses/ddp/lessons/intro/theory_unit"}],"id":698,"slug":"intro","state":"approved","name":"Введение","course_order":100,"goal":"Познакомиться с курсом и с проектом карточной игры, над которым мы будем работать в течение всего курса, по ходу знакомясь с важными концепциями программирования.","self_study":null,"theory_video_provider":"vimeo","theory_video_uid":"172391980","theory":"<figure>\n <blockquote class=\"blockquote\">\n <p>Я изобрел понятие «объектно-ориентированный», но могу заявить, что не имел в виду C++ при этом.</p>\n </blockquote>\n <figcaption class=\"blockquote-footer\">\n Alan Kay\n </figcaption>\n</figure>\n\nНа текущий момент мы уже достаточно много знаем, как строить модульные программы и теперь пришло время поговорить о том, как строить расширяемые программы. В программировании существует понятие аддитивность, и эта тема будет центральной в нашем курсе.\n**Аддитивность** – это расширение возможности вашей программы без переписывания исходного кода.\n\n## Какие темы будут разобраны?\n\n- Пользовательские типы\n- Динамическая диспетчеризация (по типу)\n- Полиморфизм\n- Передача сообщений\n- Объектно-ориентированное программирование\n\nВо-первых, это пользовательские типы (типы данных, которые мы можем создавать самостоятельно).\nМы поговорим про такое важное понятие, как диспетчеризация и конкретно о динамической диспетчеризации (по типу). Разберём понятие полиморфизма. О нём многие слышали, но очень не многие понимают, что оно по-настоящему обозначает. Эту интересную тему мы разберём в одном из последних уроков. Также мы поговорим про передачу сообщений. И, наконец, придём к пониманию объектно-ориентированного программирования: что это такое, как с ним работать и почему, например, JavaScript считается объектно-ориентированным языком.\n\n## Новый синтаксис\n\n- Свойства\n- Тип Данных: Объект\n- Классы\n\nВ этом курсе появится новый синтаксис, который включает в себя несколько понятий.\nПервое – это **свойства**, которые используются в JavaScript даже для самых базовых вещей. Мы избегали этой темы, чтобы не отвлекаться от модульности. Теперь пришло время начать с ними работать.\n\nВо-вторых, мы разберём тип данных, который называется **объект**. Это не то же самое, что объект в объектно-ориентированном программировании, но иногда названия, которые используются в языках программирования несут свой смысл, и к этому нужно будет просто привыкнуть.\n\nИ последнее, с чем мы познакомимся – это **классы**. Ниже приведён небольшой пример класса, который будет использоваться в нашей программе. Мы подробно разберем его в нашем курсе.\n\n```javascript\nexport default class PercentCard {\n constructor(name, percent) {\n this.name = name\n this.percent = percent\n }\n\n damage(health) {\n return Math.round(health * (this.percent / 100))\n }\n}\n```\n\n## Проект: Карточная игра\n\n\n\nВ этом курсе мы будем работать над своей **карточной игрой**. Она будет без графического интерфейса. Мы будем выводит процесс игры в виде текста.\n\nЭта карточная игра необычная и не такая, как все привыкли видеть, играя в обычные карты. Игра будет про волшебников, в процессе которой происходит нападение друг на друга. Каждая карта описывает атаку, урон юнита и так далее. В нашем случае она будет простая, но на ней будет хорошо видна проблематика, которую мы собираемся отрабатывать.\n\n## Процесс игры\n\nДавайте посмотрим на процесс без кода. Как будет происходить вывод нашей игры:\n\n```\nНачинаем бой!\n\nИгрок 'John' применил 'Прохладный чыонг-бонг рыка'\nпротив 'Ada' и нанес урон '3'\n\nИгрок 'Ada' применил 'Воздушный змей клеветы'\nпротив 'John' и нанес урон '1'\n\nИгрок 'John' применил 'Проказливый рубитель крови'\nпротив 'Ada' и нанес урон '2'\n\nAda был убит\n```\n\nДля карт, которые представляют собой оружие, используются названия позаимствованные из Diablo. В сети существует множество генераторов названий предметов из этой игры. Они довольно прикольные, поэтому будет здорово здесь ими воспользоваться.\n\nГлядя на процесс, очевидно, что игра рассчитана на двух игроков, которые по очереди делают ходы. Сначала один игрок наносит урон, потом второй, затем снова первый и так по кругу. Урон зависит от текущей карты. И она не всегда наносит конкретный урон. Он может зависеть от текущего здоровья (например, снимать 50% здоровья) и других характеристик.\n\nПредположим, что стартовый уровень жизни у каждого игрока 10. А тот, у кого уровень жизни дойдёт до нуля или станет отрицательным, считается убитым. В примере видно, что игрок с именем Ada был убит первым.\n\n## Разработка через тесты\n\nНаш курс будет примером разработки через так называемый Test Driven Development. Это означает, что тесты пишутся до кода.\n\n```\nДизайн кода определяется тестами.\n\nВместо того, чтобы сосредотачиваться на\nвнутреннем представлении, сначала прорабатываются\nварианты использования этого кода.\n```\n\nЗачем это нужно?\n\n **Test Driven Development** – это такая методология, которая существует уже достаточно много лет. Она входит в концепцию экстремального программирования. Её главная фишка, что мы не фокусируемся на том, как будет устроен код внутри. Гораздо важнее, как им пользоваться. Именно дизайн кода (так называемый API), интерфейс, который вы отдаёте другим для использования и является определяющим. Если вы делаете хорошую абстракцию, то внутреннее содержимое не так важно. Вы всегда можете его переписать.\n\nОчень часто бывает так (это касается не только программирования), что люди делают что-то, но пользоваться этим невозможно. Это касается всего в нашей жизни: любого производства, продукта, процесса и так далее. Test Driven Development в первую очередь, заставляет нас думать о дизайне кода, о том, как его использовать, а затем строить внутреннюю структуру.\n\n## Обучение на Хекслете\n\nПовторим аспекты, которые мы используем для того, чтобы обучение было лучше и была проработка правильных вещей.\n\n- Неизменяемость (функциональный стиль)\n- СИКП\n- Обучение через рефакторинг\n- Разработка через тесты\n- Знания, которые не устаревают\n\nМы продолжаем использовать функциональный стиль. При этом постепенно начинаем вводить изменяемость.\n\nКурс также продолжает традицию основ на СИКП.\n\nМы делаем обучение через рефакторинг, то есть мы не рассказываем сразу, как правильно что-то сделать. Чтобы понять достаточно сложные темы по-настоящему, нужно пережить опыт и самостоятельно упереться в сложности. Поэтому уроки будут построены следующим образом: мы делаем какое-то решение, которое у вас (по нашей задумке) будет вызывать вопросы «А почему так?» и будете видеть, что здесь есть какие-то недоработки. В свою очередь следующий урок будет говорить об этом подробно и уже показывать следующий шаг для решения возникших проблем, и так далее. Постепенно мы будем приходить к общему решению, которое исправляет все недостатки предыдущих. Это так называемое обучение через рефакторинг.\n\nТакже напоминаю, что в этом курсе разработка будет происходить через тесты (о чём мы уже с вами говорили).\n\nЗнания текущего курса являются универсальными. Будет совсем чуть-чуть JavaScript специфики, но в основном всё, что здесь рассказывается — это ключ к пониманию, как устроены все современные языки, и какие проблемы они решают.\n"},"id":121,"slug":"ddp","challenges_count":3,"name":"JS: Программирование, управляемое данными","allow_indexing":true,"state":"approved","course_state":"finished","pricing_type":"paid","description":"На этом курсе вы познакомитесь с программированием, управляемым данными. Вы узнаете, как использовать данные для управления логикой программы. Вы научитесь создавать динамические приложения и работать с классами, узнаете о полиморфизме и его типах, познакомитесь с диспетчеризацией по типу и аддитивностью. Знания из этого курса помогут создавать мощные и гибкие приложения, которые легко адаптируются к изменениям данных.","kind":"additional","updated_at":"2026-01-20T11:53:13.077Z","language":"javascript","duration_cache":39000,"skills":["Делать свое ООП с типами и диспетчеризацией","Использовать инверсию зависимостей для изменения поведения кода без его переписывания","Создавать классы и использовать их в JavaScript","Применять полиморфизм для уменьшения количества условных конструкций и дублирования"],"keywords":["ООП","Динамическая диспетчеризация","Типы данных","Объекты"],"lessons_count":9,"cover":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6ODkwOSwicHVyIjoiYmxvYl9pZCJ9fQ==--8d6ae873c203221995a5f2afe08cdb3b594e095f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJqcGciLCJyZXNpemVfdG9fZmlsbCI6WzYwMCw0MDBdfSwicHVyIjoidmFyaWF0aW9uIn19--39ba06fa99226096df9fc6bb31f84e1d29ea98e9/image.png"},"recommendedLandings":[{"stack":{"id":20,"slug":"js-sicp","title":"СИКП на JS","audience":"for_programmers","start_type":"anytime","pricing_model":"subscription","priority":"medium","kind":"track","state":"published","stack_state":"finished","order":4050,"duration_in_months":1},"id":28,"slug":"js-sicp","title":"СИКП на JS","subtitle":"Навык понимать программы на фундаментальном уровне, уверенно проходить собеседования и решать сложные задачи","subtitle_for_lists":"Навык фундаментального программирования","locale":"ru","current":true,"duration_in_months_text":"1 месяц","stack_slug":"js-sicp","price_text":"от 3 900 ₽","duration_text":"1 месяц","cover_list_variant":"https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png"}],"lessonMemberUnit":null,"accessToLearnUnitExists":false,"accessToCourseExists":false},"url":"/courses/ddp/lessons/polymorphism/theory_unit","version":"0b0c6d4ebbd40fd58630a0dd89cc25544ccdf24e","encryptHistory":false,"clearHistory":false}"><style data-mantine-styles="true">:root, :host{--mantine-font-family: Arial, sans-serif;--mantine-font-family-headings: Arial, sans-serif;--mantine-heading-font-weight: normal;--mantine-radius-default: 0rem;--mantine-primary-color-filled: var(--mantine-color-indigo-filled);--mantine-primary-color-filled-hover: var(--mantine-color-indigo-filled-hover);--mantine-primary-color-light: var(--mantine-color-indigo-light);--mantine-primary-color-light-hover: var(--mantine-color-indigo-light-hover);--mantine-primary-color-light-color: var(--mantine-color-indigo-light-color);--mantine-spacing-xxl: calc(4rem * var(--mantine-scale));--mantine-font-size-xs: 12px;--mantine-font-size-sm: 14px;--mantine-font-size-md: 16px;--mantine-font-size-lg: clamp(16.0000px, calc(15.2727px + 0.2273vw), 18.0000px);--mantine-font-size-xl: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-display-3: clamp(32.0000px, calc(26.1818px + 1.8182vw), 48.0000px);--mantine-font-size-display-2: clamp(36.0000px, calc(25.8182px + 3.1818vw), 64.0000px);--mantine-font-size-display-1: clamp(40.0000px, calc(25.4545px + 4.5455vw), 80.0000px);--mantine-font-size-h1: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-font-size-h2: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-font-size-h3: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-font-size-h4: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-font-size-h5: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-font-size-h6: 1rem;--mantine-primary-color-0: var(--mantine-color-indigo-0);--mantine-primary-color-1: var(--mantine-color-indigo-1);--mantine-primary-color-2: var(--mantine-color-indigo-2);--mantine-primary-color-3: var(--mantine-color-indigo-3);--mantine-primary-color-4: var(--mantine-color-indigo-4);--mantine-primary-color-5: var(--mantine-color-indigo-5);--mantine-primary-color-6: var(--mantine-color-indigo-6);--mantine-primary-color-7: var(--mantine-color-indigo-7);--mantine-primary-color-8: var(--mantine-color-indigo-8);--mantine-primary-color-9: var(--mantine-color-indigo-9);--mantine-color-red-0: #ffeaea;--mantine-color-red-1: #fed4d4;--mantine-color-red-2: #f4a7a8;--mantine-color-red-3: #ec7878;--mantine-color-red-4: #e55050;--mantine-color-red-5: #e03131;--mantine-color-red-6: #e02829;--mantine-color-red-7: #c71a1c;--mantine-color-red-8: #b21218;--mantine-color-red-9: #9c0411;--mantine-color-violet-0: #fce9ff;--mantine-color-violet-1: #f1cfff;--mantine-color-violet-2: #e09bff;--mantine-color-violet-3: #d16fff;--mantine-color-violet-4: #be37fe;--mantine-color-violet-5: #b51afe;--mantine-color-violet-6: #b009ff;--mantine-color-violet-7: #9b00e4;--mantine-color-violet-8: #8a00cc;--mantine-color-violet-9: #7800b3;--mantine-color-indigo-0: #edecff;--mantine-color-indigo-1: #d6d5fe;--mantine-color-indigo-2: #aaa9f4;--mantine-color-indigo-3: #7b79eb;--mantine-color-indigo-4: #5451e4;--mantine-color-indigo-5: #3b37e0;--mantine-color-indigo-6: #2d2adf;--mantine-color-indigo-7: #1f1ec7;--mantine-color-indigo-8: #1819b2;--mantine-color-indigo-9: #0c149e;--mantine-color-cyan-0: #dffdff;--mantine-color-cyan-1: #caf5ff;--mantine-color-cyan-2: #99e8ff;--mantine-color-cyan-3: #64daff;--mantine-color-cyan-4: #3ccffe;--mantine-color-cyan-5: #24c8fe;--mantine-color-cyan-6: #00c2ff;--mantine-color-cyan-7: #00ade4;--mantine-color-cyan-8: #009acd;--mantine-color-cyan-9: #0085b5;--mantine-color-green-0: #e9fdec;--mantine-color-green-1: #d7f6dc;--mantine-color-green-2: #b0eab9;--mantine-color-green-3: #86df94;--mantine-color-green-4: #62d574;--mantine-color-green-5: #4ccf5f;--mantine-color-green-6: #3fcc54;--mantine-color-green-7: #2fb344;--mantine-color-green-8: #25a03b;--mantine-color-green-9: #138a2e;--mantine-color-yellow-0: #fff7e2;--mantine-color-yellow-1: #ffeecd;--mantine-color-yellow-2: #ffdc9c;--mantine-color-yellow-3: #ffc966;--mantine-color-yellow-4: #feb93a;--mantine-color-yellow-5: #feae1e;--mantine-color-yellow-6: #ffa90f;--mantine-color-yellow-8: #ca8200;--mantine-color-yellow-9: #af7000;--mantine-h1-font-size: clamp(28.0000px, calc(23.6364px + 1.3636vw), 40.0000px);--mantine-h1-font-weight: normal;--mantine-h2-font-size: clamp(24.0000px, calc(21.0909px + 0.9091vw), 32.0000px);--mantine-h2-font-weight: normal;--mantine-h3-font-size: clamp(20.0000px, calc(17.0909px + 0.9091vw), 28.0000px);--mantine-h3-font-weight: normal;--mantine-h4-font-size: clamp(16.0000px, calc(13.0909px + 0.9091vw), 24.0000px);--mantine-h4-font-weight: normal;--mantine-h5-font-size: clamp(16.0000px, calc(14.5455px + 0.4545vw), 20.0000px);--mantine-h5-font-weight: normal;--mantine-h6-font-size: 1rem;--mantine-h6-font-weight: normal;}
:root[data-mantine-color-scheme="dark"], :host([data-mantine-color-scheme="dark"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-dark-filled: var(--mantine-color-dark-5);--mantine-color-dark-filled-hover: var(--mantine-color-dark-6);--mantine-color-dark-light: rgba(105, 105, 105, 0.15);--mantine-color-dark-light-hover: rgba(105, 105, 105, 0.2);--mantine-color-dark-light-color: var(--mantine-color-dark-0);--mantine-color-dark-outline: var(--mantine-color-dark-1);--mantine-color-dark-outline-hover: rgba(184, 184, 184, 0.05);--mantine-color-gray-filled: var(--mantine-color-gray-5);--mantine-color-gray-filled-hover: var(--mantine-color-gray-6);--mantine-color-gray-light: rgba(222, 226, 230, 0.15);--mantine-color-gray-light-hover: rgba(222, 226, 230, 0.2);--mantine-color-gray-light-color: var(--mantine-color-gray-0);--mantine-color-gray-outline: var(--mantine-color-gray-1);--mantine-color-gray-outline-hover: rgba(241, 243, 245, 0.05);--mantine-color-red-filled: var(--mantine-color-red-5);--mantine-color-red-filled-hover: var(--mantine-color-red-6);--mantine-color-red-light: rgba(236, 120, 120, 0.15);--mantine-color-red-light-hover: rgba(236, 120, 120, 0.2);--mantine-color-red-light-color: var(--mantine-color-red-0);--mantine-color-red-outline: var(--mantine-color-red-1);--mantine-color-red-outline-hover: rgba(254, 212, 212, 0.05);--mantine-color-pink-filled: var(--mantine-color-pink-5);--mantine-color-pink-filled-hover: var(--mantine-color-pink-6);--mantine-color-pink-light: rgba(250, 162, 193, 0.15);--mantine-color-pink-light-hover: rgba(250, 162, 193, 0.2);--mantine-color-pink-light-color: var(--mantine-color-pink-0);--mantine-color-pink-outline: var(--mantine-color-pink-1);--mantine-color-pink-outline-hover: rgba(255, 222, 235, 0.05);--mantine-color-grape-filled: var(--mantine-color-grape-5);--mantine-color-grape-filled-hover: var(--mantine-color-grape-6);--mantine-color-grape-light: rgba(229, 153, 247, 0.15);--mantine-color-grape-light-hover: rgba(229, 153, 247, 0.2);--mantine-color-grape-light-color: var(--mantine-color-grape-0);--mantine-color-grape-outline: var(--mantine-color-grape-1);--mantine-color-grape-outline-hover: rgba(243, 217, 250, 0.05);--mantine-color-violet-filled: var(--mantine-color-violet-5);--mantine-color-violet-filled-hover: var(--mantine-color-violet-6);--mantine-color-violet-light: rgba(209, 111, 255, 0.15);--mantine-color-violet-light-hover: rgba(209, 111, 255, 0.2);--mantine-color-violet-light-color: var(--mantine-color-violet-0);--mantine-color-violet-outline: var(--mantine-color-violet-1);--mantine-color-violet-outline-hover: rgba(241, 207, 255, 0.05);--mantine-color-indigo-filled: var(--mantine-color-indigo-5);--mantine-color-indigo-filled-hover: var(--mantine-color-indigo-6);--mantine-color-indigo-light: rgba(123, 121, 235, 0.15);--mantine-color-indigo-light-hover: rgba(123, 121, 235, 0.2);--mantine-color-indigo-light-color: var(--mantine-color-indigo-0);--mantine-color-indigo-outline: var(--mantine-color-indigo-1);--mantine-color-indigo-outline-hover: rgba(214, 213, 254, 0.05);--mantine-color-blue-filled: var(--mantine-color-blue-5);--mantine-color-blue-filled-hover: var(--mantine-color-blue-6);--mantine-color-blue-light: rgba(116, 192, 252, 0.15);--mantine-color-blue-light-hover: rgba(116, 192, 252, 0.2);--mantine-color-blue-light-color: var(--mantine-color-blue-0);--mantine-color-blue-outline: var(--mantine-color-blue-1);--mantine-color-blue-outline-hover: rgba(208, 235, 255, 0.05);--mantine-color-cyan-filled: var(--mantine-color-cyan-5);--mantine-color-cyan-filled-hover: var(--mantine-color-cyan-6);--mantine-color-cyan-light: rgba(100, 218, 255, 0.15);--mantine-color-cyan-light-hover: rgba(100, 218, 255, 0.2);--mantine-color-cyan-light-color: var(--mantine-color-cyan-0);--mantine-color-cyan-outline: var(--mantine-color-cyan-1);--mantine-color-cyan-outline-hover: rgba(202, 245, 255, 0.05);--mantine-color-teal-filled: var(--mantine-color-teal-5);--mantine-color-teal-filled-hover: var(--mantine-color-teal-6);--mantine-color-teal-light: rgba(99, 230, 190, 0.15);--mantine-color-teal-light-hover: rgba(99, 230, 190, 0.2);--mantine-color-teal-light-color: var(--mantine-color-teal-0);--mantine-color-teal-outline: var(--mantine-color-teal-1);--mantine-color-teal-outline-hover: rgba(195, 250, 232, 0.05);--mantine-color-green-filled: var(--mantine-color-green-5);--mantine-color-green-filled-hover: var(--mantine-color-green-6);--mantine-color-green-light: rgba(134, 223, 148, 0.15);--mantine-color-green-light-hover: rgba(134, 223, 148, 0.2);--mantine-color-green-light-color: var(--mantine-color-green-0);--mantine-color-green-outline: var(--mantine-color-green-1);--mantine-color-green-outline-hover: rgba(215, 246, 220, 0.05);--mantine-color-lime-filled: var(--mantine-color-lime-5);--mantine-color-lime-filled-hover: var(--mantine-color-lime-6);--mantine-color-lime-light: rgba(192, 235, 117, 0.15);--mantine-color-lime-light-hover: rgba(192, 235, 117, 0.2);--mantine-color-lime-light-color: var(--mantine-color-lime-0);--mantine-color-lime-outline: var(--mantine-color-lime-1);--mantine-color-lime-outline-hover: rgba(233, 250, 200, 0.05);--mantine-color-yellow-filled: var(--mantine-color-yellow-5);--mantine-color-yellow-filled-hover: var(--mantine-color-yellow-6);--mantine-color-yellow-light: rgba(255, 201, 102, 0.15);--mantine-color-yellow-light-hover: rgba(255, 201, 102, 0.2);--mantine-color-yellow-light-color: var(--mantine-color-yellow-0);--mantine-color-yellow-outline: var(--mantine-color-yellow-1);--mantine-color-yellow-outline-hover: rgba(255, 238, 205, 0.05);--mantine-color-orange-filled: var(--mantine-color-orange-5);--mantine-color-orange-filled-hover: var(--mantine-color-orange-6);--mantine-color-orange-light: rgba(255, 192, 120, 0.15);--mantine-color-orange-light-hover: rgba(255, 192, 120, 0.2);--mantine-color-orange-light-color: var(--mantine-color-orange-0);--mantine-color-orange-outline: var(--mantine-color-orange-1);--mantine-color-orange-outline-hover: rgba(255, 232, 204, 0.05);--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-9) 0%, var(--mantine-color-cyan-7) 100%);--app-color-surface: #2e2e2e;}
:root[data-mantine-color-scheme="light"], :host([data-mantine-color-scheme="light"]){--mantine-color-anchor: var(--mantine-color-text);--mantine-color-dimmed: #495057;--mantine-color-red-light: rgba(224, 40, 41, 0.1);--mantine-color-red-light-hover: rgba(224, 40, 41, 0.12);--mantine-color-red-outline-hover: rgba(224, 40, 41, 0.05);--mantine-color-violet-light: rgba(176, 9, 255, 0.1);--mantine-color-violet-light-hover: rgba(176, 9, 255, 0.12);--mantine-color-violet-outline-hover: rgba(176, 9, 255, 0.05);--mantine-color-indigo-light: rgba(45, 42, 223, 0.1);--mantine-color-indigo-light-hover: rgba(45, 42, 223, 0.12);--mantine-color-indigo-outline-hover: rgba(45, 42, 223, 0.05);--mantine-color-cyan-light: rgba(0, 194, 255, 0.1);--mantine-color-cyan-light-hover: rgba(0, 194, 255, 0.12);--mantine-color-cyan-outline-hover: rgba(0, 194, 255, 0.05);--mantine-color-green-light: rgba(63, 204, 84, 0.1);--mantine-color-green-light-hover: rgba(63, 204, 84, 0.12);--mantine-color-green-outline-hover: rgba(63, 204, 84, 0.05);--mantine-color-yellow-light: rgba(255, 169, 15, 0.1);--mantine-color-yellow-light-hover: rgba(255, 169, 15, 0.12);--mantine-color-yellow-outline-hover: rgba(255, 169, 15, 0.05);--app-color-surface: #f1f3f5;--app-cta-gradient: linear-gradient(90deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-5) 100%);}</style><style data-mantine-styles="classes">@media (max-width: 35.99375em) {.mantine-visible-from-xs {display: none !important;}}@media (min-width: 36em) {.mantine-hidden-from-xs {display: none !important;}}@media (max-width: 47.99375em) {.mantine-visible-from-sm {display: none !important;}}@media (min-width: 48em) {.mantine-hidden-from-sm {display: none !important;}}@media (max-width: 61.99375em) {.mantine-visible-from-md {display: none !important;}}@media (min-width: 62em) {.mantine-hidden-from-md {display: none !important;}}@media (max-width: 74.99375em) {.mantine-visible-from-lg {display: none !important;}}@media (min-width: 75em) {.mantine-hidden-from-lg {display: none !important;}}@media (max-width: 87.99375em) {.mantine-visible-from-xl {display: none !important;}}@media (min-width: 88em) {.mantine-hidden-from-xl {display: none !important;}}</style><div style="position:absolute;top:0rem" class=""></div><div style="max-width:var(--container-size-xl);height:100%;min-height:0rem" class=""><style data-mantine-styles="inline">.__m__-_R_5ub_{--grid-gutter:0rem;}</style><div style="height:100%;min-height:0rem" class="m_410352e9 mantine-Grid-root __m__-_R_5ub_"><div class="m_dee7bd2f mantine-Grid-inner" style="height:100%"><style data-mantine-styles="inline">.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:91.66666666666667%;--col-max-width:91.66666666666667%;}@media(min-width: 48em){.__m__-_R_rdub_{--col-flex-grow:auto;--col-flex-basis:83.33333333333334%;--col-max-width:83.33333333333334%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem;display:flex" class="m_96bdd299 mantine-Grid-col __m__-_R_rdub_"><style data-mantine-styles="inline">.__m__-_R_6qrdub_{margin-top:0rem;padding-inline:var(--mantine-spacing-xs);width:100%;}@media(min-width: 48em){.__m__-_R_6qrdub_{margin-top:var(--mantine-spacing-xl);width:80%;}}@media(min-width: 62em){.__m__-_R_6qrdub_{padding-inline:var(--mantine-spacing-xl);}}</style><div style="margin-inline:auto;max-width:var(--mantine-breakpoint-xl)" class="__m__-_R_6qrdub_"><div style="color:var(--mantine-color-dimmed)" class="m_4451eb3a mantine-Center-root" data-inline="true"><div style="--ti-size:var(--ti-size-xs);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;margin-inline-end:calc(0.125rem * var(--mantine-scale));color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="xs"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-lock "><path d="M5 13a2 2 0 0 1 2 -2h10a2 2 0 0 1 2 2v6a2 2 0 0 1 -2 2h-10a2 2 0 0 1 -2 -2v-6"></path><path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0 -2 0"></path><path d="M8 11v-4a4 4 0 1 1 8 0v4"></path></svg></div><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">JS: Программирование, управляемое данными</p></div><h1 style="--title-fw:var(--mantine-h1-font-weight);--title-lh:var(--mantine-h1-line-height);--title-fz:var(--mantine-h1-font-size);margin-bottom:var(--mantine-spacing-xl)" class="m_8a5d1357 mantine-Title-root" data-order="1">Теория: Полиморфизм</h1><script type="application/ld+json">{"@context":"https://schema.org","@type":"LearningResource","name":"Полиморфизм","inLanguage":"ru","isPartOf":{"@type":"LearningResource","name":"JS: Программирование, управляемое данными"},"isAccessibleForFree":"False","hasPart":{"@type":"WebPageElement","isAccessibleForFree":"False","cssSelector":".paywalled"}}</script><div class=""><div style="--alert-color:var(--mantine-color-indigo-light-color);margin-bottom:var(--mantine-spacing-lg);font-size:var(--mantine-font-size-lg)" class="m_66836ed3 mantine-Alert-root" id="mantine-_R_remqrdub_" role="alert" aria-describedby="mantine-_R_remqrdub_-body" aria-labelledby="mantine-_R_remqrdub_-title"><div class="m_a5d60502 mantine-Alert-wrapper"><div class="m_667f2a6a mantine-Alert-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-rocket "><path d="M4 13a8 8 0 0 1 7 7a6 6 0 0 0 3 -5a9 9 0 0 0 6 -8a3 3 0 0 0 -3 -3a9 9 0 0 0 -8 6a6 6 0 0 0 -5 3"></path><path d="M7 14a6 6 0 0 0 -3 6a6 6 0 0 0 6 -3"></path><path d="M14 9a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path></svg></div><div class="m_667c2793 mantine-Alert-body"><div class="m_6a03f287 mantine-Alert-title"><span id="mantine-_R_remqrdub_-title" class="m_698f4f23 mantine-Alert-label">Полный доступ к материалам</span></div><div id="mantine-_R_remqrdub_-body" class="m_7fa78076 mantine-Alert-message"><div style="--group-gap:var(--mantine-spacing-md);--group-align:center;--group-justify:space-between;--group-wrap:wrap" class="m_4081bf90 mantine-Group-root"><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Зарегистрируйтесь и получите доступ к этому и десяткам других курсов</p><a style="--button-height:var(--button-height-xs);--button-padding-x:var(--button-padding-x-xs);--button-fz:var(--mantine-font-size-xs);--button-bg:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-hover:linear-gradient(45deg, var(--mantine-color-blue-filled) 0%, var(--mantine-color-cyan-filled) 100%);--button-color:var(--mantine-color-white);--button-bd:none" class="mantine-focus-auto mantine-active m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root" data-variant="gradient" data-size="xs" href="/u/new"><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">Зарегистрироваться</span></span></a></div></div></div></div></div><div class="paywalled m_d08caa0 mantine-Typography-root"><p>Корректировка к слайду «Параметрический полиморфизм»:</p>
<div class="m_5cb1b9c8 mantine-CodeHighlightTabs-root"><div style="--sa-corner-width:0px;--sa-corner-height:0px" class="m_7b14120b mantine-CodeHighlightTabs-filesScrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><div class="m_38d99e51 mantine-CodeHighlightTabs-files"><button class="mantine-focus-auto m_5cac2e62 mantine-CodeHighlightTabs-file m_87cf2631 mantine-UnstyledButton-root" data-active="true" type="button"><span>javascript</span></button><button class="mantine-focus-auto m_5cac2e62 mantine-CodeHighlightTabs-file m_87cf2631 mantine-UnstyledButton-root" type="button"><span>javascript</span></button></div></div></div><div data-orientation="horizontal" class="m_c44ba933 mantine-ScrollArea-scrollbar" data-hidden="true" style="position:absolute;--sa-thumb-width:18px" data-mantine-scrollbar="true"></div><div class="m_c44ba933 mantine-ScrollArea-scrollbar" data-hidden="true" data-orientation="vertical" style="position:absolute;--sa-thumb-height:18px" data-mantine-scrollbar="true"></div></div><div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlightTabs-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlightTabs-controls" data-with-offset="true"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlightTabs-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlightTabs-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlightTabs-pre" data-with-offset="true"><code class="m_5caae6d3 mantine-CodeHighlightTabs-code">append(numbers1, numbers2)</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlightTabs-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div></div><p>--</p>
<p>В этом уроке мы поговорим немножко о терминах и о такой вещи, как полиморфизм.</p>
<h2 id="heading-2-1">Что такое полиморфизм?</h2>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">В языках программирования и теории типов полиморфизмом
называется способность функции обрабатывать данные разных типов.</code>
<h2 id="heading-2-2">На практике</h2>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Полиморфизм повышает коэффициент повторного использования кода,
то есть уменьшает дублирование.</code>
<h2 id="heading-2-3">Виды полиморфизма</h2>
<ul>
<li>Ad-hoc (Специальный)</li>
<li>Параметрический</li>
<li>Подтипов (включения)</li>
</ul>
<p>Со всеми примерами этих полиморфизмов мы уже встречались, но просто никогда не использовали эти термины.</p>
<h2 id="heading-2-4">Параметрический полиморфизм</h2>
<code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">Вызов ОДНОГО и того же кода для ВСЕХ
допустимых типов (полиморфных) аргументов.</code>
<p>Параметрический полиморфизм в теории типов и у людей, которые часто используют функциональные языки, обычно принято называть словом полиморфизм, что кстати говоря идёт в разрез с тем, что принято у программистов, которые пишут исключительно на объектно-ориентированных языках. Они под словом полиморфизм понимают полиморфизм подтипов.</p>
<p>Давайте представим ситуацию, с которой мы уже сталкивались. У нас есть список и мы вызываем операцию «собрать два списка в один»:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const numbers1 = l(3, 4, 5, 8)
const numbers2 = l(3, 2, 9)
append(numbers1, numbers2) // (3, 4, 5, 8, 2, 9)</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p><code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">append</code> берет два списка и делает из них один.</p>
<p>Ещё один пример той же самой операции, но разница в том, что теперь здесь список строк:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const strings1 = l('cat', 'dog')
const strings2 = l('table', 'milk', 'phone')
append(strings1, strings2) // (cat, dog, table, milk, phone)</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Поскольку мы работаем в динамическом языке нам без разницы с какими типами работать. Какой бы список у нас не был и какой бы тип не содержался внутри какого-то основного типа – всё будет работать.</p>
<p>В статических языках это совершенно не так и вы не можете просто так определить список чего угодно. У вас будет список конкретных структур, поэтому в таких языках нужны специальные механизмы, которые позволяют определять обобщённые списки.</p>
<p>Это важно по той простой причине, что применяя функцию <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">append</code> (операция объединения списков) можно увидеть, что над элементами, которые лежат в списке, никаких действий не производится вообще. Они не участвуют в этой операции и им не нужно это. То есть объединяя два списка мы не делаем никаких преобразований внутри. Соответственно, эта операция в общем случае не зависит от того, что хранится внутри.</p>
<p>Идеально – язык программирования должен позволять нам работать с этим именно так.</p>
<p>Как мы уже говорили, в динамических языках мы получаем параметрический полиморфизм из коробки и действительно – функция <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">append</code> одна для любых списков, потому что мы не делаем здесь никаких различий, код будет один и его будет довольно мало.</p>
<p>В статических языках нет механизма для поддержки параметрического полиморфизма, им придётся писать функцию <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">append</code> для каждого типа. Представьте себе сколько может быть списков и сколько вообще может быть таких структур, для которых придётся так делать. По этой причине там существуют специальные механизмы.
Особенно эти проблемы существуют в объектно-ориентированных языках, потому что в функциональных языках параметрический полиморфизм есть всегда и из коробки – это основа, а вот например, в таких языках как Java, существует специальный механизм, который называется <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://en.wikipedia.org/wiki/Generics_in_Java" rel="noopener noreferrer" target="_blank">дженерики</a>. В C++ существует механизм, который называется <a style="text-decoration:underline" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="https://ru.wikipedia.org/wiki/%D0%A8%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%8B_C++" rel="noopener noreferrer" target="_blank">темплейты</a>.</p>
<p>В каких-то других языках это может называться по-другому, но всё это сводится к тому, чтобы иметь возможность пользоваться параметрическим полиморфизмом у себя в языке.</p>
<h2 id="heading-2-5">Ad-hoc полиморфизм</h2>
<p>Это самый простой тип полиморфизма. Он связан с тем, что в зависимости от типов аргументов применяется разная реализация какой-то операции.</p>
<p>Например, в данном случае сложения:</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">1 + 1 // 2
'cat' + 'dog' // catdog
console.log(1034.98) // => 1034.98
console.log('hello') // => hello</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Если у нас типы число и число, то у нас будет арифметическая операция. Если у нас две строчки, то это будет конкатенация. Если будут разные типы, то там уже зависит от ситуации.</p>
<p>Причём в статических языках, опять же, ad-hoc полиморфизм реализуется за счёт перегрузки функций (то есть описываются разные тела функций, в которых задаются разные типы аргументов) и соответственно компилятор сам выбирает какую функцию в какой момент использовать. Внутри нет никаких if’ов, то есть мы уже работаем конкретно с теми типами, которые мы определили в данной функции. Под одним именем одной операции скрывается несколько разных тел.</p>
<p>В динамических языках мы этого делать не можем, поэтому там по сути всегда это сводится к тому, что у вас есть одна функция, внутри которой много if’ов, которые проверяют типы аргументов.</p>
<p>Например, если посмотреть исходники <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">console.log</code>, можно увидеть, что там это примерно так и устроено. Там используется функция формат, которая внутри проверяет типы аргументов и в зависимости от типа делает какие-то разные действия.</p>
<h2 id="heading-2-6">Полиморфизм подтипов</h2>
<p>Напомню, что полиморфизм подтипов в объектно-ориентированных языках называют просто полиморфизм, что не совсем корректно.</p>
<p>Как раз этот полиморфизм позволяет вызывать РАЗНЫЙ код для РАЗНЫХ иерархий типов.</p>
<div style="margin-bottom:var(--mantine-spacing-lg)" class="m_e597c321 mantine-CodeHighlight-codeHighlight" dir="ltr"><div class="m_be7e9c9c mantine-CodeHighlight-controls"><button style="--ai-bg:transparent;--ai-hover:transparent;--ai-color:inherit;--ai-bd:none" class="mantine-focus-auto mantine-active m_d498bab7 mantine-CodeHighlight-control m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="none" type="button" aria-label="Copy code"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 8m0 2a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2z"></path><path d="M16 8v-2a2 2 0 0 0 -2 -2h-8a2 2 0 0 0 -2 2v8a2 2 0 0 0 2 2h2"></path></svg></span></button></div><div style="--scrollarea-scrollbar-size:calc(0.25rem * var(--mantine-scale));--sa-corner-width:0px;--sa-corner-height:0px" class="m_f744fd40 mantine-CodeHighlight-scrollarea m_d57069b5 mantine-ScrollArea-root" dir="ltr"><div style="overflow-x:hidden;overflow-y:hidden;overscroll-behavior-inline:none" class="m_c0783ff9 mantine-ScrollArea-viewport" data-scrollbars="xy"><div class="m_b1336c6 mantine-ScrollArea-content"><pre class="m_2c47c4fd mantine-CodeHighlight-pre" style="padding:0"><code class="m_5caae6d3 mantine-CodeHighlight-code">const obj = new SimpleCard() // or PercentCard()
obj.damage(health)</code></pre></div></div></div><button class="mantine-focus-auto m_c9378bc2 mantine-CodeHighlight-showCodeButton m_87cf2631 mantine-UnstyledButton-root" data-hidden="true" type="button">Expand code</button></div>
<p>Собственно, с этим полиморфизмом мы сквозь весь наш курс в первую очередь и знакомились и использовали его в нашей программе. И именно задача нашего курса была завести внутри языка полиморфизм подтипов.</p>
<p>Полиморфизм подтипов является ключевой штукой для ООП.</p>
<p>Почему это нужно – мы уже прекрасно знаем. Бывает, что для разных типов нужно вызывать разную реализацию одних и тех же (с точки зрения интерфейса) функций для того, чтобы не писать <code style="margin-bottom:var(--mantine-spacing-lg)" class="m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight m_e597c321 mantine-CodeHighlight-codeHighlight m_dfe9c588 mantine-InlineCodeHighlight-inlineCodeHighlight">if</code>.
Это как раз к вопросу о том, что эта штука исключительно просто сокращает код с точки зрения практики, а формально вы, конечно, можете работать и без него.</p>
<h2 id="heading-2-7">Итоги</h2>
<p>Полиморфизм связан с динамической диспетчеризацией, которую мы разбирали. Просто динамическая диспетчеризация – это один из способов реализации полиморфизма.</p>
<p>Любой язык и любая штука, с которой мы работаем, позволяет нам использовать полиморфизм и как раз с помощью динамической диспетчеризации мы можем его, собственно, реализовать и таким образом просто сокращать тот код, который мы пишем.</p></div><div style="margin-block:var(--mantine-spacing-xl)" class=""><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md)" class="m_8a5d1357 mantine-Title-root" data-order="2">Рекомендуемые программы</h2><style data-mantine-styles="inline">.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xs);--carousel-slide-size:70%;}@media(min-width: 36em){.__m__-_R_2mremqrdub_{--carousel-slide-gap:var(--mantine-spacing-xl);--carousel-slide-size:50%;}}</style><div style="--carousel-control-size:calc(2.5rem * var(--mantine-scale));--carousel-controls-offset:var(--mantine-spacing-sm);margin-bottom:var(--mantine-spacing-lg);padding-block:var(--mantine-spacing-sm);background:var(--app-color-surface)" class="m_17884d0f mantine-Carousel-root responsiveClassName" data-orientation="horizontal" data-include-gap-in-size="true"><div class="m_39bc3463 mantine-Carousel-controls" data-orientation="horizontal"><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="previous" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button><button class="mantine-focus-auto m_64f58e10 mantine-Carousel-control m_87cf2631 mantine-UnstyledButton-root" type="button" data-inactive="true" data-type="next" tabindex="-1"><svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg);width:calc(1rem * var(--mantine-scale));height:calc(1rem * var(--mantine-scale));display:block"><path d="M3.13523 6.15803C3.3241 5.95657 3.64052 5.94637 3.84197 6.13523L7.5 9.56464L11.158 6.13523C11.3595 5.94637 11.6759 5.95657 11.8648 6.15803C12.0536 6.35949 12.0434 6.67591 11.842 6.86477L7.84197 10.6148C7.64964 10.7951 7.35036 10.7951 7.15803 10.6148L3.15803 6.86477C2.95657 6.67591 2.94637 6.35949 3.13523 6.15803Z" fill="currentColor" fill-rule="evenodd" clip-rule="evenodd"></path></svg></button></div><div class="m_a2dae653 mantine-Carousel-viewport" data-type="media"><div class="m_fcd81474 mantine-Carousel-container __m__-_R_2mremqrdub_" data-orientation="horizontal"><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/programs/js-sicp?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card" target="_blank"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><div style="--group-gap:calc(0.25rem * var(--mantine-scale));--group-align:center;--group-justify:flex-start;--group-wrap:nowrap" class="m_4081bf90 mantine-Group-root"><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">1 месяц</span><span class="mantine-focus-auto m_b6d8b162 mantine-Text-root">·</span><span style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Для продвинутых</span></div><p style="margin-bottom:var(--mantine-spacing-sm);font-size:var(--mantine-font-size-h5);font-weight:bold" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">СИКП на JS</p><p class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Навык фундаментального программирования</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="https://hexlet.io/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6Mzc2MCwicHVyIjoiYmxvYl9pZCJ9fQ==--9348098e4053d798b6f34bee4ef66947540261e4/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbNDAwLDQwMF0sInNhdmVyIjp7InF1YWxpdHkiOjg1fX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--5b6f46dacd1af664f27558553a58076185091823/Low%20code%20development-rafiki.png" alt="СИКП на JS" loading="eager"/></div><div style="--group-gap:var(--mantine-spacing-md);--group-align:end;--group-justify:space-between;--group-wrap:wrap;margin-top:var(--mantine-spacing-xs)" class="m_4081bf90 mantine-Group-root"><p style="font-size:var(--mantine-font-size-xl)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">от 3 900 ₽</p><p style="font-size:var(--mantine-font-size-sm)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Посмотреть →</p></div></div></div></a></div></div><div class="m_d98df724 mantine-Carousel-slide" data-orientation="horizontal"><div tabindex="0" style="cursor:pointer;height:100%"><a style="text-decoration:none" class="mantine-focus-auto m_849cf0da m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses?promo_name=programs_list&promo_position=course&promo_creative=catalog_card&promo_type=card"><div style="height:100%" class="m_e615b15f mantine-Card-root m_1b7284a3 mantine-Paper-root" data-with-border="true"><h2 style="--title-fw:var(--mantine-h2-font-weight);--title-lh:var(--mantine-h2-line-height);--title-fz:var(--mantine-h2-font-size);margin-bottom:var(--mantine-spacing-md);font-size:var(--mantine-font-size-h3)" class="m_8a5d1357 mantine-Title-root" data-order="2" data-responsive="true">Каталог</h2><p style="margin-bottom:auto" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Полный список доступных курсов по разным направлениям</p><div style="margin-top:auto" class=""><div class="m_4451eb3a mantine-Center-root"><img style="opacity:0.8;width:70%" class="m_9e117634 mantine-Image-root mantine-visible-from-xs" src="/vite/assets/development-BVihs_d5.png" alt="Orientation"/></div></div></div></a></div></div></div></div></div></div></div></div></div><style data-mantine-styles="inline">.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:8.333333333333334%;--col-max-width:8.333333333333334%;}@media(min-width: 48em){.__m__-_R_1bdub_{--col-flex-grow:auto;--col-flex-basis:16.666666666666668%;--col-max-width:16.666666666666668%;}}</style><div style="min-width:0rem;height:100%;min-height:0rem" class="m_96bdd299 mantine-Grid-col __m__-_R_1bdub_"><div style="margin-inline:var(--mantine-spacing-xs)" class="mantine-visible-from-sm"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-lg);text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/ddp/lessons/polymorphism/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label"><span style="margin-inline-end:var(--mantine-spacing-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Дальше</span>→</span></span></a><a style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Навигация по теме</span><span class="m_57492dcc mantine-NavLink-description">Теория</span></div><span class="m_690090b5 mantine-NavLink-section" data-position="right"></span></a><div style="margin-block:var(--mantine-spacing-lg)" class="m_3eebeb36 mantine-Divider-root" data-orientation="horizontal" role="separator"></div><div style="margin-block:var(--mantine-spacing-lg)" class=""><div style="justify-content:space-between;margin-bottom:calc(0.1875rem * var(--mantine-scale));color:var(--mantine-color-dimmed);font-size:var(--mantine-font-size-xs)" class="m_8bffd616 mantine-Flex-root __m__-_R_qimrbdub_"><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">Завершено</p><p style="font-size:var(--mantine-font-size-xs)" class="mantine-focus-auto m_b6d8b162 mantine-Text-root">0 / 9</p></div><div style="--progress-size:var(--progress-size-sm)" class="m_db6d6462 mantine-Progress-root" data-size="sm"><div style="--progress-section-size:0%;--progress-section-color:var(--mantine-color-gray-filled)" class="m_2242eb65 mantine-Progress-section" role="progressbar" aria-valuemax="100" aria-valuemin="0" aria-valuenow="0" aria-valuetext="0%"></div></div></div><button style="padding-inline:0rem" class="mantine-focus-auto m_f0824112 mantine-NavLink-root m_87cf2631 mantine-UnstyledButton-root" type="button"><span class="m_690090b5 mantine-NavLink-section" data-position="left"><div style="--ti-size:var(--ti-size-sm);--ti-bg:transparent;--ti-color:var(--mantine-color-indigo-light-color);--ti-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;color:inherit" class="m_7341320d mantine-ThemeIcon-root" data-variant="transparent" data-size="sm"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></div></span><div class="m_f07af9d2 mantine-NavLink-body"><span class="m_1f6ac4c4 mantine-NavLink-label">Обсуждения (архив)</span><span class="m_57492dcc mantine-NavLink-description"></span></div></button><div style="--toc-bg:var(--mantine-color-blue-light);--toc-color:var(--mantine-color-blue-light-color);--toc-size:var(--mantine-font-size-sm);--toc-radius:var(--mantine-radius-sm);margin-top:var(--mantine-spacing-xl)" class="m_bcaa9990 mantine-TableOfContents-root" data-variant="light" data-size="sm"></div></div><div class="mantine-hidden-from-sm"><div style="--stack-gap:0rem;--stack-align:stretch;--stack-justify:flex-start" class="m_6d731127 mantine-Stack-root"><a style="--button-color:var(--mantine-color-white);margin-bottom:var(--mantine-spacing-xs);padding:0rem;text-decoration:none" class="mantine-focus-auto m_849cf0da mantine-focus-auto m_77c9d27d mantine-Button-root m_87cf2631 mantine-UnstyledButton-root m_b6d8b162 mantine-Text-root mantine-Anchor-root" data-underline="hover" href="/courses/ddp/lessons/polymorphism/finish_unit?unit=theory" data-disabled="true" data-block="true" disabled=""><span class="m_80f1301b mantine-Button-inner"><span class="m_811560b9 mantine-Button-label">→</span></span></a><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" data-disabled="true" type="button" disabled=""><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-list-numbers "><path d="M11 6h9"></path><path d="M11 12h9"></path><path d="M12 18h8"></path><path d="M4 16a2 2 0 1 1 4 0c0 .591 -.5 1 -1 1.5l-3 2.5h4"></path><path d="M6 10v-6l-2 2"></path></svg></span></button><button style="--ai-size:var(--ai-size-sm);--ai-bg:transparent;--ai-hover:var(--mantine-color-indigo-light-hover);--ai-color:var(--mantine-color-indigo-light-color);--ai-bd:calc(0.0625rem * var(--mantine-scale)) solid transparent;padding-block:var(--mantine-spacing-lg);color:inherit;width:100%" class="mantine-focus-auto mantine-active m_8d3f4000 mantine-ActionIcon-root m_87cf2631 mantine-UnstyledButton-root" data-variant="subtle" data-size="sm" type="button"><span class="m_8d3afb97 mantine-ActionIcon-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" class="tabler-icon tabler-icon-message "><path d="M8 9h8"></path><path d="M8 13h6"></path><path d="M18 4a3 3 0 0 1 3 3v8a3 3 0 0 1 -3 3h-5l-5 3v-3h-2a3 3 0 0 1 -3 -3v-8a3 3 0 0 1 3 -3h12"></path></svg></span></button></div></div></div></div></div></div></div>
</main>
<footer class="bg-dark fw-light text-light px-3 py-5">
<div class="row small">
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 mb-3">Хекслет</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/about">О нас</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/testimonials">Отзывы</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://b2b.hexlet.io" role="button">Корпоративное обучение</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/blog">Блог</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/qna">Вопросы и ответы</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/glossary">Глоссарий</a>
</li>
<li>
<span class="nav-link link-light py-1 ps-0 external-link" data-href="https://help.hexlet.io" data-target="_blank" role="button">Справка</span>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" target="_blank" rel="noopener noreferrer" href="/map">Карта сайта</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5 fw-normal mb-3">Направления</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_devops">DevOps
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_data_analytics">Аналитика
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_backend_development">Бэкенд
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_programming">Программирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_testing">Тестирование
</a></li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/courses_front_end_dev">Фронтенд
</a></li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Профессии</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/devops-engineer-from-scratch">DevOps-инженер с нуля</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/go">Go-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/java">Java-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python">Python-разработчик </a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/data-analytics">Аналитик данных</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/qa-engineer">Инженер по ручному тестированию</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php">РНР-разработчик</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/frontend">Фронтенд-разработчик</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-6 col-md-3">
<div class="h5">Навыки</div>
<ul class="list-unstyled">
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/python-django-developer">Django</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/docker">Docker</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/php-laravel-developer">Laravel</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/postman">Postman</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-react-developer">React</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/js-rest-api">REST API в Node.js</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/spring-boot">Spring Boot</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/programs/typescript">Typescript</a>
</li>
</ul>
</div>
</div>
<hr>
<div class="row">
<div class="col-12 col-sm-4 col-md-2">
<div class="fs-4">
<ul class="list-unstyled d-flex">
<li class="me-3">
<a aria-label="Telegram" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://t.me/hexlet_ru"><span class="bi bi-telegram"></span>
</a></li>
<li>
<a aria-label="Youtube" target="_blank" class="link-light" rel="noopener noreferrer nofollow" href="https://www.youtube.com/user/HexletUniversity"><span class="bi bi-youtube"></span>
</a></li>
</ul>
</div>
<div class="mb-2 d-flex flex-column">
<a class="link-light text-decoration-none" rel="nofollow" href="mailto:support@hexlet.io">support@hexlet.io</a>
<a class="link-light text-decoration-none py-2" target="_blank" href="https://t.me/hexlet_help_bot">t.me/hexlet_help_bot</a>
</div>
<ul class="list-unstyled d-flex">
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://hexlet.io/locale/switch?new_locale=en" data-target="_self" role="button"><span class="my-auto">EN</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 opacity-100 external-link" rel="nofollow" data-href="https://ru.hexlet.io/locale/switch?new_locale=ru" data-target="_self" role="button"><span class="my-auto">RU</span>
</span></li>
<li class="me-3">
<span class="link-light text-decoration-none opacity-50 x-font-size-18 external-link" rel="nofollow" data-href="https://kz.hexlet.io/locale/switch?new_locale=kz" data-target="_self" role="button"><span class="my-auto">KZ</span>
</span></li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<ul class="list-unstyled fs-4">
<li class="mb-3">
<a class="link-light text-decoration-none" href="tel:8%20800%20100%2022%2047">8 800 100 22 47</a>
<span class="d-block opacity-50 small">бесплатно по РФ</span>
</li>
<li>
<a class="link-light text-decoration-none" href="tel:%2B7%20495%20085%2021%2062">+7 495 085 21 62</a>
<span class="d-block opacity-50 small">бесплатно по Москве</span>
</li>
</ul>
</div>
<div class="col-12 col-sm-4 col-md-3">
<div class="small mb-3">Образовательные услуги оказываются на основании Л035-01298-77/01989008 от 14.03.2025</div>
<ul class="list-unstyled small">
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/legal">Правовая информация</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/offer">Оферта</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/license">Лицензия</a>
</li>
<li>
<a class="nav-link link-light py-1 ps-0" href="/pages/contacts">Контакты</a>
</li>
</ul>
</div>
<div class="col-12 col-sm-12 col-md-4 small">
<div class="mb-2">
<div>ООО «<a href="/" class="text-decoration-none link-light">Хекслет Рус</a>»</div>
<div>108813 г. Москва, вн.тер.г. поселение Московский,</div>
<div>г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3</div>
<div>ОГРН 1217300010476</div>
<div>ИНН 7325174845</div>
</div>
<hr>
<div>АНО ДПО «<a href="/" class="text-decoration-none link-light">Учебный центр «Хекслет</a>»</div>
<div>119331 г. Москва, вн. тер. г. муниципальный округ</div>
<div>Ломоносовский, пр-кт Вернадского, д. 29</div>
<div>ОГРН 1247700712390</div>
<div>ИНН 7736364948</div>
</div>
</div>
</footer>
<div id="root-assistant-offcanvas"></div>
<script src="/vite/assets/assistant-CdBlNCiQ.js" crossorigin="anonymous" type="module"></script><link rel="modulepreload" href="/vite/assets/chunk-DsPFFUou.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/init-nkZBEvfU.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/ErrorFallbackBlock-naDSYSy9.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/MarkdownBlock-DbyKWoR_.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/gon-D3e4yh1x.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/mantine-CGMYrt2Y.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/shiki-V011pkdv.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/utils-DRqSHbQE.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/routes-CCH8ilKF.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-XR8Qr8kR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dist-GCHh59xr.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/Box-B5-OOzBf.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/notifications.store-C-3AFSMn.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useIsomorphicEffect-HJ6VK0D3.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/lib-KSp6QbZ0.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/axios-BEvgo0ym.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/classnames-l6ipYlLR.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/dayjs.min-BkKovM-s.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/debounce-jMQ_Cf4f.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/i18next-BlSq9s7B.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/client-U9M77rxp.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-dom-DaLxUz_h.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/useTranslation-Bx1Cdrkz.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/compiler-runtime-6XxiPFnt.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/jsx-runtime-CwjcCKJi.js" as="script" crossorigin="anonymous">
<link rel="modulepreload" href="/vite/assets/react-CkL4ZRHB.js" as="script" crossorigin="anonymous">
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v67327c56f0bb4ef8b305cae61679db8f1769101564043" integrity="sha512-rdcWY47ByXd76cbCFzznIcEaCN71jqkWBBqlwhF1SY7KubdLKZiEGeP7AyieKZlGP9hbY/MhGrwXzJC/HulNyg==" data-cf-beacon='{"version":"2024.11.0","token":"d11015b65d11429ea6b4a2ef37dd7e0b","server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
</body>
</html>