Вопрос проверяет глубину понимания полиморфизма и знание его различных форм.
Существует несколько видов полиморфизма: через наследование, через протоколы, параметрический и ad-hoc. В Swift наиболее активно используются полиморфизм через протоколы и параметрический полиморфизм с помощью дженериков. Каждый вид решает свою задачу. Выбор зависит от требований к гибкости и типобезопасности. Все они направлены на уменьшение связности кода.
Полиморфизм — это не только наследование. В разных языках и в Swift в частности, он проявляется по-разному, и важно понимать, чем эти формы отличаются.
Он работает, когда выбор реализации происходит во время выполнения.
Обычно это:
наследование и переопределение (override)
вызов метода через базовый тип
Пример идеи:
переменная типа Shape
внутри может быть Circle или Rectangle
вызов area() выполнит нужную реализацию
Ключевая особенность:
гибкость высокая
но есть небольшая цена на диспетчеризацию
В Swift протоколы часто являются основным способом полиморфизма.
Он работает через:
общий контракт (протокол)
разные типы, реализующие методы протокола
Плюсы:
можно «подмешивать» поведение без иерархий наследования
удобно для тестов, потому что легко подменять реализации
Минусы:
могут появляться нюансы с existential и производительностью, если тип стирается до протокола
Это ситуация, когда код пишется один раз, но работает с разными типами, и выбор происходит на этапе компиляции.
Пример:
Array<T>
функция func max<T: Comparable>(...) -> T
Плюсы:
обычно быстрее, потому что не требует динамического выбора
более строгая типобезопасность
Минусы:
иногда сложнее читать и поддерживать, если дженерики слишком сложные
Это «полиморфизм под конкретные типы», чаще всего через перегрузку функций.
В Swift:
можно перегружать методы по сигнатуре
но это не то же самое, что динамический полиморфизм
В Swift чаще всего применяются две формы: полиморфизм через протоколы и параметрический полиморфизм через дженерики. Наследование используется реже, но остаётся важным, особенно в UIKit.