Начнём знакомство с полиморфизмом подтипов с задачки. Представьте себе функцию, которая проверяет, есть ли комментарии у статьи или топика (вопросы пользователей Хекслета под уроками и проектами). Статья в коде представлена объектом класса 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 выполняется идентично. Во втором — алгоритм построен вокруг самого объекта и использует его методы. В полиморфизме подтипов полиморфная функция работает только с теми объектами, которые имеют необходимые для реализации алгоритма методы.
Вам ответят команда поддержки Хекслета или другие студенты.
Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.
Загляните в раздел «Обсуждение»:
Статья «Ловушки обучения»
Вебинар «Как самостоятельно учиться»
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.
Наши выпускники работают в компаниях:
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Зарегистрируйтесь или войдите в свой аккаунт