Обычно выделяют несколько разновидностей полиморфизма:
• Полиморфизм подтипов.
Отношение «is a». Возможность использовать данные одного типа в параметре другого типа, без изменения кода. Определяется принципом подстановки Лисков. Этот вид используется при вызове переопределенных методов (override).
Такой полиморфизм – почти то же самое что наследование. Но наследование подразумевает переиспользование кода, а например совместимость инвариантных типов в Java – отношение «is a», но не наследование.
• Параметрический полиморфизм.
Способность функции или класса принимать параметры разных типов. Реализуется дженериками и темплейтами в ООП языках, полиморфными функциями в ФП.
• Ad-hoc полиморфизм.
Возможность вызвать разный код в зависимости от типа параметров. Не совсем настоящий полиморфизм, потому что замена типа заменяет и реализацию обработки. Пример – перегрузка методов (overload). Если конкретный метод разрешается при компиляции – называется статическим, иначе – динамическим.
• Полиморфизм записей.
Кортеж (row) – объект типа запись, объединенный набор полей данных, то что в C называется structure. Это полиморфизм в условиях утиной типизации. Метод применим к любым кортежам, которые содержат все поля, используемые в этом методе. Так работает например TypeScript.
• Полиморфизм принуждения (coercion polymorphism).
Если нет метода для такого типа параметра, параметр неявно приводится к ожидаемому типу. Он применяется например для оператора
+
в JavaScript, когда мы пытаемся прибавить к числу строку (4 + "2" === "42"
).