В истинном духе этого блога я собираюсь взять сложную идею полиморфизма и сделать ее максимально простой.
Возможно, вы уже думаете, что понимаете полиморфизм — и, возможно, понимаете — но я обнаружил, что большинство разработчиков программного обеспечения не совсем понимают, что такое полиморфизм.
Что такое полиморфизм?
Сколько раз вам задавали этот вопрос во время собеседования?
Вы действительно знаете , уверенно , что правильный ответ?
Не волнуйтесь, если вы похожи на большинство разработчиков в мире, у вас, вероятно, возникает ощущение, что вы знаете, что такое полиморфизм, но не в состоянии дать четкое и краткое его определение.
Большинство разработчиков понимают примеры полиморфизма или одного конкретного типа полиморфизма, но не понимают саму концепцию.
Позвольте мне немного уточнить.
Под этим я подразумеваю, что много раз, когда я спрашиваю о полиморфизме в интервью, я получаю ответ в виде примера:
Чаще всего разработчик будет описывать, как базовый класс формы может иметь производный класс от окружности и квадратный производный класс, и когда вы вызываете метод draw для ссылки на базовый класс формы, правильная реализация отрисовки производного класса вызывается без вас специально необходимость знать тип.
Хотя это технически правильный пример полиморфизма во время выполнения, он никоим образом не является кратким и не является определением фактического термина.
Я сам описывал полиморфизм подобным образом во многих собеседованиях.
Истинное понимание
Проблема только с этим примером в качестве объяснения заключается в том, что ему не хватает истинного понимания концепции.
Это похоже на умение читать, запоминая слова, но не понимая концепций фонетики, лежащих в основе истинной концепции чтения.
Хорошим тестом для понимания концепции является способность создать хорошую аналогию для этой концепции.
Часто, если человек не может придумать аналогию для описания концепции, это происходит потому, что ему не хватает истинного понимания того, что такое концепция.
Аналогии также являются отличным способом обучения понятиям , связывая вещи с другой вещью, которая уже понятна.
Если сейчас вы не можете придумать реальную аналогию полиморфизма, не волнуйтесь, что вы не одиноки.
Основное определение
Теперь, когда мы понимаем, почему большинство из нас действительно не понимают полиморфизм, давайте начнем с очень простого и краткого определения.
Полиморфизм является обмен общего интерфейса для нескольких типов, но имеющий разные реализации для разных типов.
В основном это означает, что в любой ситуации, когда у вас есть один и тот же интерфейс для чего-то, но вы можете по-разному вести себя в зависимости от типа, у вас есть полиморфизм.
Подумайте о проигрывателе Blu-ray.
Когда вы кладете обычный DVD в плеер, что происходит?
Как насчет того, когда вы вставляете диск Blu-ray в плеер?
Интерфейс плеера одинаков для обоих типов носителей, но поведение отличается. Внутренне существует различная реализация действия воспроизведения диска в зависимости от типа.
Как насчет торгового автомата?
Вы когда-нибудь вносили изменения в торговый автомат?
Вы, вероятно, положили монеты разных номиналов или типов в один слот в автомате, но поведение автомата было различным в зависимости от типа.
Если вы поместите четверть в машину, она будет стоить 25 центов Если вы положите в 10 центов, то вы получите 10 центов.
И это все, теперь вы понимаете реальную концепцию полиморфизма.
Хотите убедиться, что вы не забыли это? Попробуйте придумать несколько собственных аналогий из реального мира или примеров полиморфизма.
Возвращение к коду
В коде полиморфизм может проявляться по-разному.
Большинство разработчиков знакомы с полиморфизмом во время выполнения, который распространен во многих ОО-языках, таких как C #, Java и C ++, но существует много других видов полиморфизма.
Рассмотрим метод перегрузки.
Если я создаю два метода с одинаковыми именами, но они различаются только по типу, у меня полиморфное поведение.
Интерфейс для вызова метода будет таким же, но тип будет определять, какой метод на самом деле вызывается.
Add(int a, int b) Add(decimal a, decimal b)
Возможно, вы качаете головой «нет», думая, что это не полиморфизм, но на мгновение дайте мне преимущество сомнения.
Наиболее распространенным аргументом против этого примера как полиморфизма является то, что при написании этого кода вызываемый метод известен во время компиляции.
Хотя это действительно так для статически типизированных и скомпилированных языков, это не так для всех языков.
Считайте, что Add является сообщением вместо метода.
Под этим я подразумеваю, что если учесть, что фактическое определение метода, вызываемого в этой ситуации, может отличаться до времени выполнения, у нас будет ситуация, очень похожая на пример обычной формы. ( Позднее связывание )
На многих языках так и происходит. Например, в Objective-C или Smalltalk сообщения фактически передаются между объектами, и получатель сообщения определяет, что делать во время выполнения.
Дело в том, что полиморфизм может быть сделан во время компиляции или во время выполнения , это не имеет значения.
Другие полиморфные примеры в коде
Поскольку цель этого поста состоит не в том, чтобы классифицировать и объяснить каждый тип полиморфизма, который существует в коде, а в том, чтобы обеспечить упрощенное понимание общей концепции, я не буду вдаваться в подробное объяснение всех видов полиморфизма, которые мы видим в коде сегодня. Вместо этого я приведу список некоторых распространенных примеров, которые вы, возможно, не поняли, были на самом деле полиморфными.
- Перегрузка оператора (аналогично перегрузке метода.)
- Обобщение и шаблонное программирование. (Здесь вы повторно используете исходный код, но фактический машинный код, выполняемый компьютером, отличается для разных типов.)
- Предварительная обработка (макросы в C и C ++)
- Тип преобразования
Почему важно понимание полиморфизма
Возможно, я ошибаюсь, но я предсказываю, что все больше и больше разработки будут отходить от традиционных ОО, поскольку мы склонны находить другие способы модульного кода, который не столь укоренен в концепции иерархий классов.
Часть перехода требует понимания полиморфизма как общей цели и полезной концепции информатики, а не очень ситуативной ОО-методики.
Несмотря на это, я думаю, вы согласитесь, что лучше иметь возможность описывать сам полиморфизм, а не приводить часто используемый пример форм.