Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Утиная типизация JS: Полиморфизм

Начнем знакомство с полиморфизмом подтипов с задачки. Представьте себе функцию, которая проверяет, есть ли комментарии у статьи или топика (вопросы пользователей Хекслета под уроками и проектами). Статья в коде представлена объектом класса Article, а топик — Topic.

const hasComments = (commentable) => {
  // Если это статья
  if (commentable instanceof Article) {
    return commentable.getArticleComments().length > 0;
  // Если это топик
  } else if (commentable instanceof Topic) {
    return commentable.getTopicComments().length > 0;
  }
}

class Article {
  // some code

  getArticleComments() {
    return this.comments;
  }
}

class Topic {
  // some code

  getTopicsComments() {
    return this.comments;
  }
}

// Article.first() — метод, который возвращает первую статью из базы данных
const article = Article.first();
console.log(hasComments(article));

С подобным кодом мы уже сталкивались ранее. Каждый новый тип потребует от нас добавления кода в эту условную конструкцию. Его можно заменить на диспетчеризацию по ключу, но особенно лучше не станет. Все равно придется описывать поведение для каждого класса в дополнение к тому, что поведение и так описано внутри каждого класса. Но можно сделать кое-что лучше. Достаточно согласовать интерфейс всех типов и договориться о том, что метод для извлечения комментариев будет называться getComments(). Тогда код станет таким:

const hasComments = (commentable) => commentable.getComments().length > 0;

const article = Article.first();
console.log(hasComments(article));

const topic = Topic.first();
console.log(hasComments(topic));

Теперь функцию hasComments(commentable) можно вызывать с любым объектом, имеющим метод getComments() с необходимой сигнатурой. Эта функция не поменяется даже при добавлении нового класса, содержащего такой же метод.

Способность функции обрабатывать объекты разных типов одинаковым образом — называется полиморфизмом подтипов, а сама функция — полиморфной функцией.

Как видно из кода выше, для реализации такого полиморфизма, в JavaScript не нужно наследование и интерфейсы. В мире такой подход называют «утиной типизацией». Если что-то ходит как утка и крякает как утка, то это утка.

Технически, самое простое и понятное, что делает полиморфизм подтипов (для клиентского кода) — убирает условные конструкции. Любую условную конструкцию можно заменить полиморфизмом и любую полиморфную функцию можно заменить на if. Другими словами, полиморфизм подтипов не является неотъемлемой частью разработки, код можно писать и без него. С другой стороны, иногда встречаются ситуации, в которых он здорово помогает, но не сказать, что это происходит постоянно.

В чем разница между параметрическим полиморфизмом и полиморфизмом подтипов? В первом случае реализуется общий алгоритм для контейнера (например массива), который содержит значение или значения типа T. Этот алгоритм не зависит от T и для любых T выполняется идентично. Во втором — алгоритм построен вокруг самого объекта и использует его методы. В полиморфизме подтипов полиморфная функция работает только с теми объектами, которые имеют необходимые для реализации алгоритма методы.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля
профессия
от 9 900 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 25 апреля
профессия
от 6 300 ₽ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 25 апреля

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»